File tree Expand file tree Collapse file tree 6 files changed +69
-4
lines changed
ktor-client-android/jvm/src/io/ktor/client/engine/android
ktor-client-tests/common/test/io/ktor/client/tests
ktor-http/common/src/io/ktor/http
ktor-test-server/src/main/kotlin/test/server Expand file tree Collapse file tree 6 files changed +69
-4
lines changed Original file line number Diff line number Diff line change @@ -25,7 +25,7 @@ jetty-alpn-api = "1.1.3.v20160715"
2525jetty-alpn-openjdk8 = " 9.4.57.v20241219"
2626
2727tomcat = " 9.0.105"
28- tomcat-jakarta = " 10.1.40 "
28+ tomcat-jakarta = " 10.1.41 "
2929
3030apache = " 4.1.5"
3131apache5 = " 5.5"
Original file line number Diff line number Diff line change @@ -24,8 +24,6 @@ import java.util.*
2424import javax.net.ssl.HttpsURLConnection
2525import 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 }
Original file line number Diff line number Diff line change 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" )
Original file line number Diff line number Diff 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/* *
Original file line number Diff line number Diff line change @@ -31,6 +31,7 @@ internal fun Application.tests() {
3131 }
3232
3333 authTestServer()
34+ echoTest()
3435 encodingTestServer()
3536 serializationTestServer()
3637 cacheTestServer()
Original file line number Diff line number Diff line change 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+ }
You can’t perform that action at this time.
0 commit comments