Skip to content

Commit

Permalink
KTOR-7596 Make multipart Content-Type check case-insensitive (#4413)
Browse files Browse the repository at this point in the history
  • Loading branch information
osipxd authored Oct 29, 2024
1 parent 5a7bf7f commit 8c271cb
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2022 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.client.plugins.contentnegotiation
Expand All @@ -16,6 +16,6 @@ public object JsonContentTypeMatcher : ContentTypeMatcher {
}

val value = contentType.withoutParameters().toString()
return value.startsWith("application/") && value.endsWith("+json")
return value.startsWith("application/", ignoreCase = true) && value.endsWith("+json", ignoreCase = true)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.client.plugins.json

Expand All @@ -13,6 +13,6 @@ internal class JsonContentTypeMatcher : ContentTypeMatcher {
}

val value = contentType.withoutParameters().toString()
return value.startsWith("application/") && value.endsWith("+json")
return value.startsWith("application/", ignoreCase = true) && value.endsWith("+json", ignoreCase = true)
}
}
6 changes: 2 additions & 4 deletions ktor-http/ktor-http-cio/jvm/src/io/ktor/http/cio/Multipart.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.http.cio
Expand All @@ -11,7 +11,6 @@ import io.ktor.utils.io.core.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.io.*
import kotlinx.io.IOException
import kotlinx.io.bytestring.*
import java.io.EOFException
import java.nio.*
Expand Down Expand Up @@ -148,14 +147,13 @@ public fun CoroutineScope.parseMultipart(
/**
* Starts a multipart parser coroutine producing multipart events
*/
@Suppress("DEPRECATION_ERROR")
public fun CoroutineScope.parseMultipart(
input: ByteReadChannel,
contentType: CharSequence,
contentLength: Long?,
maxPartSize: Long = Long.MAX_VALUE,
): ReceiveChannel<MultipartEvent> {
if (!contentType.startsWith("multipart/")) {
if (!contentType.startsWith("multipart/", ignoreCase = true)) {
throw IOException("Failed to parse multipart: Content-Type should be multipart/* but it is $contentType")
}
val boundaryByteBuffer = parseBoundaryInternal(contentType)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.tests.http.cio

import io.ktor.http.cio.*
import io.ktor.utils.io.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.test.*
import kotlinx.io.*
import kotlin.test.*

@OptIn(DelicateCoroutinesApi::class)
Expand Down Expand Up @@ -335,6 +337,17 @@ class MultipartTest {
}
}

@Test
fun testParseContentType() = runTest {
fun testContentType(contentType: String) {
parseMultipart(ByteReadChannel.Empty, "$contentType; boundary=A", 0L)
}

testContentType("multipart/mixed")
testContentType("Multipart/mixed")
assertFailsWith<IOException> { testContentType("multi-part/mixed") }
}

@OptIn(DelicateCoroutinesApi::class)
@Test
fun testEmptyPayload() = runBlocking {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2023 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.server.jetty.jakarta
Expand All @@ -8,7 +8,6 @@ import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.response.*
import io.ktor.util.*
import io.ktor.util.cio.*
import io.ktor.util.pipeline.*
import io.ktor.utils.io.*
Expand Down Expand Up @@ -72,7 +71,7 @@ internal class JettyKtorHandler(
) {
try {
val contentType = request.contentType
if (contentType != null && contentType.startsWith("multipart/")) {
if (contentType != null && contentType.startsWith("multipart/", ignoreCase = true)) {
baseRequest.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, multipartConfig)
// TODO someone reported auto-cleanup issues so we have to check it
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

package io.ktor.server.jetty
Expand All @@ -8,7 +8,6 @@ import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.response.*
import io.ktor.util.*
import io.ktor.util.cio.*
import io.ktor.util.pipeline.*
import io.ktor.utils.io.*
Expand Down Expand Up @@ -72,7 +71,7 @@ internal class JettyKtorHandler(
) {
try {
val contentType = request.contentType
if (contentType != null && contentType.startsWith("multipart/")) {
if (contentType != null && contentType.startsWith("multipart/", ignoreCase = true)) {
baseRequest.setAttribute(Request.MULTIPART_CONFIG_ELEMENT, multipartConfig)
// TODO someone reported auto-cleanup issues so we have to check it
}
Expand Down

0 comments on commit 8c271cb

Please sign in to comment.