HTTP engine abstraction and configuration for different backend implementations like Apache HttpClient, OkHttp, and CIO. The engine system provides a pluggable architecture that allows switching between different HTTP implementations while maintaining a consistent API.
Base interface for all HTTP client engines providing the core execution and lifecycle management.
/**
* Base interface for HTTP client engines
*/
interface HttpClientEngine : CoroutineScope, Closeable {
/** Coroutine dispatcher for I/O operations */
val dispatcher: CoroutineDispatcher
/** Engine configuration */
val config: HttpClientEngineConfig
/** Set of capabilities supported by this engine */
val supportedCapabilities: Set<HttpClientEngineCapability<*>>
/** Coroutine context for the engine */
override val coroutineContext: CoroutineContext
/**
* Execute an HTTP request and return response data
*/
suspend fun execute(data: HttpRequestData): HttpResponseData
/**
* Install this engine into the specified client
*/
fun install(client: HttpClient)
/**
* Close the engine and release resources
*/
override fun close()
}Factory interface for creating engine instances with configuration.
/**
* Factory for creating HTTP client engines
*/
interface HttpClientEngineFactory<out T : HttpClientEngineConfig> {
/**
* Create an engine instance with the given configuration
*/
fun create(block: T.() -> Unit = {}): HttpClientEngine
}Base configuration class for all HTTP engines with common settings.
/**
* Base configuration for HTTP client engines
*/
abstract class HttpClientEngineConfig {
/** Custom coroutine dispatcher for I/O operations */
var dispatcher: CoroutineDispatcher? = null
/** Enable HTTP pipelining (where supported) */
var pipelining: Boolean = false
/** Proxy configuration */
var proxy: ProxyConfig? = null
/** Number of threads in the engine thread pool */
var threadsCount: Int = 4
}System for declaring and checking engine capabilities.
/**
* Represents a capability that an engine may support
*/
class HttpClientEngineCapability<T>(name: String) {
companion object {
/**
* Create a new capability with the given name
*/
fun <T> create(name: String): HttpClientEngineCapability<T>
}
}
/**
* Common engine capabilities
*/
object EngineCapabilities {
/** WebSocket support capability */
val WebSocketCapability: HttpClientEngineCapability<Unit>
/** HTTP/2 support capability */
val HTTP2Capability: HttpClientEngineCapability<Unit>
/** Server-Sent Events support capability */
val SSECapability: HttpClientEngineCapability<Unit>
}Proxy support for routing requests through intermediary servers.
/**
* Base proxy configuration
*/
abstract class ProxyConfig {
/** Proxy server URL */
abstract val url: Url
}
/**
* HTTP proxy configuration
*/
class ProxyBuilder {
companion object {
/**
* Create HTTP proxy configuration
*/
fun http(url: String): ProxyConfig
/**
* Create SOCKS proxy configuration
*/
fun socks(host: String, port: Int): ProxyConfig
}
}JVM-specific proxy configuration with authentication support.
/**
* JVM HTTP proxy configuration with authentication
*/
class HttpProxyConfig(
override val url: Url
) : ProxyConfig() {
/** Proxy authentication credentials */
var credentials: ProxyCredentials? = null
}
/**
* JVM SOCKS proxy configuration
*/
class SocksProxyConfig(
override val url: Url
) : ProxyConfig() {
/** SOCKS version (4 or 5) */
var version: Int = 5
/** SOCKS authentication credentials */
var credentials: ProxyCredentials? = null
}
/**
* Proxy authentication credentials
*/
data class ProxyCredentials(
val username: String,
val password: String
)ServiceLoader mechanism for automatic engine discovery on JVM platform.
/**
* ServiceLoader container for engine discovery
*/
interface HttpClientEngineContainer {
/** Engine factory instance */
val factory: HttpClientEngineFactory<*>
}
/**
* Load available engines using ServiceLoader
*/
fun loadEngines(): List<HttpClientEngineFactory<*>>
/**
* Get default engine factory
*/
fun getDefaultEngine(): HttpClientEngineFactory<*>Connection pooling and lifecycle management configuration.
/**
* Connection pool configuration base class
*/
abstract class ConnectionPoolConfig {
/** Maximum number of connections per route */
var maxConnectionsPerRoute: Int = 5
/** Maximum total number of connections */
var maxConnectionsTotal: Int = 20
/** Connection keep-alive time in milliseconds */
var keepAliveTime: Long = 60_000
/** Connection idle timeout in milliseconds */
var connectionIdleTimeout: Long = 30_000
}Configuration classes for different engine implementations.
/**
* Apache HttpClient engine configuration
*/
class ApacheEngineConfig : HttpClientEngineConfig() {
/** Socket timeout in milliseconds */
var socketTimeout: Int = 0
/** Connection timeout in milliseconds */
var connectTimeout: Int = 0
/** Connection request timeout in milliseconds */
var connectionRequestTimeout: Int = 0
/** Custom SSL context */
var sslContext: SSLContext? = null
/** Follow redirects automatically */
var followRedirects: Boolean = true
/** Custom connection manager */
var customizeClient: (HttpClientBuilder) -> Unit = {}
/** Custom request configuration */
var customizeRequest: (RequestConfig.Builder) -> Unit = {}
}
/**
* OkHttp engine configuration
*/
class OkHttpConfig : HttpClientEngineConfig() {
/** Connection timeout in milliseconds */
var connectTimeout: Duration = Duration.ofSeconds(10)
/** Read timeout in milliseconds */
var readTimeout: Duration = Duration.ofSeconds(10)
/** Write timeout in milliseconds */
var writeTimeout: Duration = Duration.ofSeconds(10)
/** Follow redirects automatically */
var followRedirects: Boolean = true
/** Follow SSL redirects automatically */
var followSslRedirects: Boolean = true
/** Custom OkHttpClient configuration */
var config: OkHttpClient.Builder.() -> Unit = {}
/** Add network interceptor */
fun addNetworkInterceptor(interceptor: Interceptor)
/** Add application interceptor */
fun addInterceptor(interceptor: Interceptor)
}
/**
* CIO (Coroutine I/O) engine configuration
*/
class CIOEngineConfig : HttpClientEngineConfig() {
/** Maximum number of connections */
var maxConnectionsCount: Int = 1000
/** Endpoint configuration */
var endpoint: EndpointConfig = EndpointConfig()
/** HTTPS configuration */
var https: HttpsConfig = HttpsConfig()
/** Request timeout in milliseconds */
var requestTimeout: Long = 15_000
}
/**
* Java HTTP client engine configuration (Java 11+)
*/
class JavaHttpEngineConfig : HttpClientEngineConfig() {
/** HTTP version preference */
var version: HttpClient.Version = HttpClient.Version.HTTP_2
/** Follow redirects policy */
var followRedirects: HttpClient.Redirect = HttpClient.Redirect.NORMAL
/** Connection timeout */
var connectTimeout: Duration = Duration.ofSeconds(10)
/** Custom Java HttpClient configuration */
var config: HttpClient.Builder.() -> Unit = {}
}Usage Examples:
import io.ktor.client.*
import io.ktor.client.engine.apache.*
import io.ktor.client.engine.okhttp.*
import io.ktor.client.engine.cio.*
import io.ktor.client.engine.java.*
import io.ktor.client.request.*
// Apache HttpClient engine
val apacheClient = HttpClient(Apache) {
engine {
socketTimeout = 30_000
connectTimeout = 10_000
connectionRequestTimeout = 5_000
followRedirects = false
// Custom SSL configuration
sslContext = SSLContext.getDefault()
// Proxy configuration
proxy = ProxyBuilder.http("http://proxy.company.com:8080")
// Custom client configuration
customizeClient { builder ->
builder.setMaxConnPerRoute(10)
builder.setMaxConnTotal(50)
}
// Custom request configuration
customizeRequest { requestConfig ->
requestConfig.setSocketTimeout(25_000)
}
}
}
// OkHttp engine
val okHttpClient = HttpClient(OkHttp) {
engine {
connectTimeout = Duration.ofSeconds(15)
readTimeout = Duration.ofSeconds(30)
writeTimeout = Duration.ofSeconds(30)
followRedirects = true
followSslRedirects = true
// Proxy configuration
proxy = ProxyBuilder.socks("socks.proxy.com", 1080)
// Custom OkHttp configuration
config {
retryOnConnectionFailure(true)
connectionPool(ConnectionPool(10, 5, TimeUnit.MINUTES))
// Add interceptors
addInterceptor { chain ->
val request = chain.request().newBuilder()
.addHeader("User-Agent", "MyApp/1.0")
.build()
chain.proceed(request)
}
}
// Add network interceptor
addNetworkInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
})
}
}
// CIO engine (Kotlin native coroutine-based)
val cioClient = HttpClient(CIO) {
engine {
maxConnectionsCount = 500
requestTimeout = 20_000
endpoint {
maxConnectionsPerRoute = 8
keepAliveTime = 120_000
connectionIdleTimeout = 60_000
}
https {
serverName = "api.example.com"
cipherSuites = CIOCipherSuites.SupportedSuites
trustManager = X509TrustManager { /* custom trust manager */ }
}
}
}
// Java HTTP Client engine (Java 11+)
val javaClient = HttpClient(Java) {
engine {
version = HttpClient.Version.HTTP_2
followRedirects = HttpClient.Redirect.NORMAL
connectTimeout = Duration.ofSeconds(20)
config {
executor(Executors.newCachedThreadPool())
cookieHandler(CookieManager())
authenticator(Authenticator.getDefault())
}
}
}
// Check engine capabilities
if (apacheClient.isSupported(EngineCapabilities.HTTP2Capability)) {
println("Apache engine supports HTTP/2")
}
if (cioClient.isSupported(EngineCapabilities.WebSocketCapability)) {
println("CIO engine supports WebSockets")
}
// Engine with custom capability
val customCapability = HttpClientEngineCapability.create<String>("CustomFeature")
// Access engine configuration
val engineConfig = apacheClient.engineConfig as ApacheEngineConfig
println("Socket timeout: ${engineConfig.socketTimeout}ms")
// Using engine factory directly
val engineFactory = Apache
val customEngine = engineFactory.create {
socketTimeout = 45_000
proxy = ProxyBuilder.http("http://custom.proxy:3128")
}
val factoryClient = HttpClient(customEngine) {
expectSuccess = false
}
// Close clients
apacheClient.close()
okHttpClient.close()
cioClient.close()
javaClient.close()
factoryClient.close()
// For proper shutdown with custom engine
customEngine.close()Secure connection configuration for HTTPS requests.
/**
* HTTPS configuration for CIO engine
*/
class HttpsConfig {
/** Server name for SNI */
var serverName: String? = null
/** Supported cipher suites */
var cipherSuites: List<CipherSuite> = CIOCipherSuites.SupportedSuites
/** Custom trust manager */
var trustManager: X509TrustManager? = null
/** Custom SSL context */
var sslContext: SSLContext? = null
/** Certificate verification */
var certificateVerifier: CertificateVerifier? = null
}
/**
* Certificate verifier interface
*/
interface CertificateVerifier {
fun verify(hostname: String, session: SSLSession): Boolean
}Endpoint-specific configuration for connection management.
/**
* Endpoint configuration for CIO engine
*/
class EndpointConfig {
/** Maximum connections per route */
var maxConnectionsPerRoute: Int = 100
/** Keep-alive time in milliseconds */
var keepAliveTime: Long = 5000
/** Connection pipeline size */
var pipelineMaxSize: Int = 20
/** Connection idle timeout */
var connectionIdleTimeout: Long = 2000
/** Connect timeout per attempt */
var connectTimeout: Long = 5000
/** Connect retry attempts */
var connectAttempts: Int = 5
}