Skip to content

Commit 1018552

Browse files
authored
Merge branch 'main' into stexxe/netty-headers-removal-race
2 parents aedc802 + 70a44a1 commit 1018552

File tree

6 files changed

+69
-4
lines changed

6 files changed

+69
-4
lines changed

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jetty-alpn-api = "1.1.3.v20160715"
2525
jetty-alpn-openjdk8 = "9.4.57.v20241219"
2626

2727
tomcat = "9.0.105"
28-
tomcat-jakarta = "10.1.40"
28+
tomcat-jakarta = "10.1.41"
2929

3030
apache = "4.1.5"
3131
apache5 = "5.5"

ktor-client/ktor-client-android/jvm/src/io/ktor/client/engine/android/AndroidClientEngine.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ import java.util.*
2424
import javax.net.ssl.HttpsURLConnection
2525
import kotlin.coroutines.CoroutineContext
2626

27-
private val METHODS_WITHOUT_BODY = listOf(HttpMethod.Get, HttpMethod.Head)
28-
2927
/**
3028
* An Android client engine.
3129
*
@@ -64,7 +62,7 @@ public class AndroidClientEngine(override val config: AndroidEngineConfig) : Htt
6462

6563
config.requestConfig(this)
6664

67-
if (data.method in METHODS_WITHOUT_BODY) {
65+
if (!data.method.supportsRequestBody) {
6866
if (outgoingContent.isEmpty()) {
6967
return@apply
7068
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2014-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package io.ktor.client.tests
6+
7+
import io.ktor.client.*
8+
import io.ktor.client.request.*
9+
import io.ktor.client.test.base.*
10+
import io.ktor.http.*
11+
import kotlin.test.Test
12+
import kotlin.test.assertEquals
13+
14+
class HttpMethodTest : ClientLoader() {
15+
16+
@Test
17+
fun `all HTTP methods should be supported`() = clientTests {
18+
test { client ->
19+
for (method in client.supportedMethods()) {
20+
val response = client.request("$TEST_SERVER/echo/method") { this.method = method }
21+
assertEquals(HttpStatusCode.OK, response.status)
22+
assertEquals(method.value, response.headers["Http-Method"])
23+
}
24+
}
25+
}
26+
}
27+
28+
private val allMethods = HttpMethod.DefaultMethods + HttpMethod.Trace
29+
30+
private fun HttpClient.supportedMethods(): List<HttpMethod> = when (engineName) {
31+
// PATCH is not supported by HttpURLConnection
32+
// https://bugs.openjdk.org/browse/JDK-7016595
33+
"AndroidClientEngine" -> allMethods - HttpMethod.Patch
34+
// Js engine throws: TypeError: 'TRACE' HTTP method is unsupported.
35+
"JsClientEngine" -> allMethods - HttpMethod.Trace
36+
else -> allMethods
37+
}
38+
39+
private val HttpClient.engineName get() = engine::class.simpleName
40+
private val HttpMethod.Companion.Trace get() = HttpMethod("TRACE")

ktor-http/common/src/io/ktor/http/HttpMethod.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ private val REQUESTS_WITHOUT_BODY = setOf(
5959
HttpMethod.Get,
6060
HttpMethod.Head,
6161
HttpMethod.Options,
62+
HttpMethod("TRACE"),
6263
)
6364

6465
/**

ktor-test-server/src/main/kotlin/test/server/ClientTestServer.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ internal fun Application.tests() {
3131
}
3232

3333
authTestServer()
34+
echoTest()
3435
encodingTestServer()
3536
serializationTestServer()
3637
cacheTestServer()
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2014-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package test.server.tests
6+
7+
import io.ktor.http.*
8+
import io.ktor.server.application.*
9+
import io.ktor.server.response.*
10+
import io.ktor.server.routing.*
11+
12+
internal fun Application.echoTest() {
13+
routing {
14+
route("/echo") {
15+
route("/method") {
16+
handle {
17+
val method = call.request.local.method.value
18+
// Some methods don't allow body, so return result in a header
19+
call.response.header("Http-Method", method)
20+
call.response.status(HttpStatusCode.OK)
21+
}
22+
}
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)