From 402b1655f8dd3ec5d227bc76de211edddc169721 Mon Sep 17 00:00:00 2001 From: Osip Fatkullin Date: Wed, 15 Jan 2025 13:59:38 +0100 Subject: [PATCH] Fixes after update to v5.4 --- .../api/ktor-client-apache5.api | 2 ++ .../client/engine/apache5/Apache5Engine.kt | 35 +++++++++++-------- .../engine/apache5/Apache5EngineConfig.kt | 18 +++++++++- .../engine/apache5/ApacheResponseConsumer.kt | 27 ++++++++------ 4 files changed, 56 insertions(+), 26 deletions(-) diff --git a/ktor-client/ktor-client-apache5/api/ktor-client-apache5.api b/ktor-client/ktor-client-apache5/api/ktor-client-apache5.api index 9f7dd8a9e97..caec5ae8711 100644 --- a/ktor-client/ktor-client-apache5/api/ktor-client-apache5.api +++ b/ktor-client/ktor-client-apache5/api/ktor-client-apache5.api @@ -15,11 +15,13 @@ public final class io/ktor/client/engine/apache5/Apache5EngineConfig : io/ktor/c public final fun getFollowRedirects ()Z public final fun getSocketTimeout ()I public final fun getSslContext ()Ljavax/net/ssl/SSLContext; + public final fun getSslHostnameVerificationPolicy ()Lorg/apache/hc/client5/http/ssl/HostnameVerificationPolicy; public final fun setConnectTimeout (J)V public final fun setConnectionRequestTimeout (J)V public final fun setFollowRedirects (Z)V public final fun setSocketTimeout (I)V public final fun setSslContext (Ljavax/net/ssl/SSLContext;)V + public final fun setSslHostnameVerificationPolicy (Lorg/apache/hc/client5/http/ssl/HostnameVerificationPolicy;)V } public final class io/ktor/client/engine/apache5/Apache5EngineContainer : io/ktor/client/HttpClientEngineContainer { diff --git a/ktor-client/ktor-client-apache5/jvm/src/io/ktor/client/engine/apache5/Apache5Engine.kt b/ktor-client/ktor-client-apache5/jvm/src/io/ktor/client/engine/apache5/Apache5Engine.kt index a09d6ce351a..125f0ebd1c2 100644 --- a/ktor-client/ktor-client-apache5/jvm/src/io/ktor/client/engine/apache5/Apache5Engine.kt +++ b/ktor-client/ktor-client-apache5/jvm/src/io/ktor/client/engine/apache5/Apache5Engine.kt @@ -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-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. */ package io.ktor.client.engine.apache5 @@ -9,19 +9,22 @@ import io.ktor.client.plugins.* import io.ktor.client.plugins.sse.* import io.ktor.client.request.* import io.ktor.utils.io.* -import kotlinx.coroutines.* -import org.apache.hc.client5.http.config.* -import org.apache.hc.client5.http.impl.async.* -import org.apache.hc.client5.http.impl.nio.* -import org.apache.hc.client5.http.ssl.* -import org.apache.hc.core5.http.* -import org.apache.hc.core5.http.ssl.* -import org.apache.hc.core5.io.* -import org.apache.hc.core5.reactor.* -import org.apache.hc.core5.ssl.* -import org.apache.hc.core5.util.* -import java.net.* -import java.util.concurrent.* +import kotlinx.coroutines.Job +import org.apache.hc.client5.http.config.ConnectionConfig +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder +import org.apache.hc.client5.http.impl.async.HttpAsyncClients +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder +import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder +import org.apache.hc.core5.http.HttpHost +import org.apache.hc.core5.http.ssl.TLS +import org.apache.hc.core5.io.CloseMode +import org.apache.hc.core5.reactor.IOReactorConfig +import org.apache.hc.core5.ssl.SSLContexts +import org.apache.hc.core5.util.Timeout +import java.net.InetSocketAddress +import java.net.Proxy +import java.util.concurrent.TimeUnit private const val MAX_CONNECTIONS_COUNT = 1000 private const val IO_THREAD_COUNT_DEFAULT = 4 @@ -89,6 +92,10 @@ internal class Apache5Engine(override val config: Apache5EngineConfig) : HttpCli ClientTlsStrategyBuilder.create() .setSslContext(config.sslContext ?: SSLContexts.createSystemDefault()) .setTlsVersions(TLS.V_1_3, TLS.V_1_2) + // TODO: Uncomment this line and remove apply after update to v5.5 + // https://github.com/apache/httpcomponents-client/commit/001eff70646c982c8c4a7c8a385d92f42579f2b5 + // .setHostVerificationPolicy(config.sslHostnameVerificationPolicy) + .apply { setHostnameVerificationPolicy(config.sslHostnameVerificationPolicy) } .build() ) .setDefaultConnectionConfig( diff --git a/ktor-client/ktor-client-apache5/jvm/src/io/ktor/client/engine/apache5/Apache5EngineConfig.kt b/ktor-client/ktor-client-apache5/jvm/src/io/ktor/client/engine/apache5/Apache5EngineConfig.kt index ab68958c14e..81ee8a4dbb8 100644 --- a/ktor-client/ktor-client-apache5/jvm/src/io/ktor/client/engine/apache5/Apache5EngineConfig.kt +++ b/ktor-client/ktor-client-apache5/jvm/src/io/ktor/client/engine/apache5/Apache5EngineConfig.kt @@ -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-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. */ package io.ktor.client.engine.apache5 @@ -7,6 +7,7 @@ package io.ktor.client.engine.apache5 import io.ktor.client.engine.* import org.apache.hc.client5.http.config.RequestConfig import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder +import org.apache.hc.client5.http.ssl.HostnameVerificationPolicy import javax.net.ssl.SSLContext /** @@ -47,6 +48,21 @@ public class Apache5EngineConfig : HttpClientEngineConfig() { */ public var sslContext: SSLContext? = null + /** + * Specifies the policy for verifying hostnames during SSL/TLS connections. + * + * The policy determines when hostname verification occurs during the connection process: + * - During TLS handshake (by JSSE) + * - After TLS handshake (by HttpClient) + * - Or both (default) + * + * Default value is [HostnameVerificationPolicy.BOTH] which provides maximum security + * by performing verification at both stages. + * + * @see HostnameVerificationPolicy + */ + public var sslHostnameVerificationPolicy: HostnameVerificationPolicy = HostnameVerificationPolicy.BOTH + internal var customRequest: (RequestConfig.Builder.() -> RequestConfig.Builder) = { this } internal var customClient: (HttpAsyncClientBuilder.() -> HttpAsyncClientBuilder) = { this } diff --git a/ktor-client/ktor-client-apache5/jvm/src/io/ktor/client/engine/apache5/ApacheResponseConsumer.kt b/ktor-client/ktor-client-apache5/jvm/src/io/ktor/client/engine/apache5/ApacheResponseConsumer.kt index 4c0695a3577..0a1fcc479e2 100644 --- a/ktor-client/ktor-client-apache5/jvm/src/io/ktor/client/engine/apache5/ApacheResponseConsumer.kt +++ b/ktor-client/ktor-client-apache5/jvm/src/io/ktor/client/engine/apache5/ApacheResponseConsumer.kt @@ -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-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. */ package io.ktor.client.engine.apache5 @@ -7,16 +7,21 @@ package io.ktor.client.engine.apache5 import io.ktor.client.request.* import io.ktor.util.* import io.ktor.utils.io.* -import kotlinx.atomicfu.* +import kotlinx.atomicfu.atomic import kotlinx.coroutines.* -import kotlinx.coroutines.channels.* +import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED -import org.apache.hc.core5.concurrent.* -import org.apache.hc.core5.http.* -import org.apache.hc.core5.http.nio.* -import org.apache.hc.core5.http.protocol.* -import java.nio.* -import kotlin.coroutines.* +import org.apache.hc.core5.concurrent.CallbackContribution +import org.apache.hc.core5.concurrent.FutureCallback +import org.apache.hc.core5.http.EntityDetails +import org.apache.hc.core5.http.Header +import org.apache.hc.core5.http.HttpResponse +import org.apache.hc.core5.http.nio.AsyncEntityConsumer +import org.apache.hc.core5.http.nio.AsyncResponseConsumer +import org.apache.hc.core5.http.nio.CapacityChannel +import org.apache.hc.core5.http.protocol.HttpContext +import java.nio.ByteBuffer +import kotlin.coroutines.CoroutineContext private object CloseChannel @@ -28,8 +33,8 @@ internal class BasicResponseConsumer(private val dataConsumer: ApacheResponseCon override fun consumeResponse( response: HttpResponse, entityDetails: EntityDetails?, - httpContext: HttpContext, - resultCallback: FutureCallback + context: HttpContext?, + resultCallback: FutureCallback, ) { responseDeferred.complete(response) if (entityDetails != null) {