From ddc3ff367a73fe891bccdc18ccf0e8feb6d32ee2 Mon Sep 17 00:00:00 2001 From: "leonid.stashevsky" Date: Thu, 17 Aug 2023 09:06:14 +0200 Subject: [PATCH] KTOR-6190 Handle NPE in JavaClientEngine body() call (#3728) (cherry picked from commit 3bc2917fc56c065b0f49c7a61aba3a7cce6ac805) --- .../ktor/client/engine/java/JavaHttpEngine.kt | 4 +++- .../ktor/client/engine/java/JavaHttpResponse.kt | 4 ++-- .../ktor/client/engine/java/JavaEngineTests.kt | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/ktor-client/ktor-client-java/jvm/src/io/ktor/client/engine/java/JavaHttpEngine.kt b/ktor-client/ktor-client-java/jvm/src/io/ktor/client/engine/java/JavaHttpEngine.kt index a9f3a833022..e335263fe83 100644 --- a/ktor-client/ktor-client-java/jvm/src/io/ktor/client/engine/java/JavaHttpEngine.kt +++ b/ktor-client/ktor-client-java/jvm/src/io/ktor/client/engine/java/JavaHttpEngine.kt @@ -60,7 +60,9 @@ public class JavaHttpEngine(override val config: JavaHttpConfig) : HttpClientEng if (data.isUpgradeRequest()) { engine.executeWebSocketRequest(callContext, data) } else { - engine.executeHttpRequest(callContext, data) + engine.executeHttpRequest(callContext, data) ?: throw kotlinx.coroutines.CancellationException( + "Request was cancelled" + ) } } catch (cause: Throwable) { callContext.cancel(CancellationException("Failed to execute request", cause)) diff --git a/ktor-client/ktor-client-java/jvm/src/io/ktor/client/engine/java/JavaHttpResponse.kt b/ktor-client/ktor-client-java/jvm/src/io/ktor/client/engine/java/JavaHttpResponse.kt index 81266ae60aa..209eef0587f 100644 --- a/ktor-client/ktor-client-java/jvm/src/io/ktor/client/engine/java/JavaHttpResponse.kt +++ b/ktor-client/ktor-client-java/jvm/src/io/ktor/client/engine/java/JavaHttpResponse.kt @@ -13,10 +13,10 @@ import kotlin.coroutines.* internal suspend fun HttpClient.executeHttpRequest( callContext: CoroutineContext, requestData: HttpRequestData -): HttpResponseData { +): HttpResponseData? { val httpRequest = requestData.convertToHttpRequest(callContext) return try { - sendAsync(httpRequest, JavaHttpResponseBodyHandler(callContext)).await().body() + sendAsync(httpRequest, JavaHttpResponseBodyHandler(callContext))?.await()?.body() } catch (cause: HttpConnectTimeoutException) { throw ConnectTimeoutException(requestData, cause) } catch (cause: HttpTimeoutException) { diff --git a/ktor-client/ktor-client-java/jvm/test/io/ktor/client/engine/java/JavaEngineTests.kt b/ktor-client/ktor-client-java/jvm/test/io/ktor/client/engine/java/JavaEngineTests.kt index 77f435ce50c..e917b18e200 100644 --- a/ktor-client/ktor-client-java/jvm/test/io/ktor/client/engine/java/JavaEngineTests.kt +++ b/ktor-client/ktor-client-java/jvm/test/io/ktor/client/engine/java/JavaEngineTests.kt @@ -8,8 +8,10 @@ import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.plugins.* import io.ktor.client.request.* +import io.ktor.client.statement.* import io.ktor.http.* import kotlinx.coroutines.* +import java.net.* import java.time.* import java.util.concurrent.* import kotlin.test.* @@ -25,6 +27,21 @@ class JavaEngineTests { } } + @Test + fun testProxy() = runBlocking { + + val client = HttpClient(Java) { + engine { + proxy = Proxy(Proxy.Type.HTTP, InetSocketAddress("localhost", 8082)) + } + } + + val body = client.get("http://127.0.0.1:8080/") + .bodyAsText() + + assertEquals("proxy", body) + } + @Test fun testThreadLeak() = runBlocking { System.setProperty("jdk.internal.httpclient.selectorTimeout", "50")