CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-ktor--ktor-client-core-jvm

Ktor HTTP client core library providing asynchronous HTTP client capabilities for Kotlin multiplatform applications

Pending
Overview
Eval results
Files

engine-architecture.mddocs/

Engine Architecture

Client engine abstraction allowing different HTTP implementations with engine-specific configuration, capabilities management, and pluggable backend support for various HTTP client implementations.

Capabilities

HttpClientEngine Interface

Core engine interface that all HTTP client implementations must implement.

/**
 * HTTP client engine interface
 */
interface HttpClientEngine : CoroutineScope, Closeable {
    /** Engine configuration */
    val config: HttpClientEngineConfig
    
    /** Coroutine dispatcher for engine operations */
    val dispatcher: CoroutineDispatcher
    
    /** Set of capabilities supported by this engine */
    val supportedCapabilities: Set<HttpClientEngineCapability<*>>
    
    /** Execute HTTP request and return response data */
    suspend fun execute(data: HttpRequestData): HttpResponseData
    
    /** Install engine in HTTP client */
    fun install(client: HttpClient)
    
    /** Close engine and release resources */
    override fun close()
}

HttpClientEngineFactory

Factory interface for creating engine instances.

/**
 * Factory for creating HTTP client engines
 */
interface HttpClientEngineFactory<T : HttpClientEngineConfig> {
    /** Create engine instance with configuration */
    fun create(block: T.() -> Unit = {}): HttpClientEngine
}

/**
 * Engine container for default engine selection
 */
object HttpClientEngineContainer {
    /** Default engine for current platform */
    val default: HttpClientEngine
    
    /** Install engine factory */
    fun install(factory: HttpClientEngineFactory<*>)
}

Usage Examples:

import io.ktor.client.engine.cio.*
import io.ktor.client.engine.apache.*

// Create client with specific engine
val cioClient = HttpClient(CIO) {
    engine {
        maxConnectionsCount = 1000
        endpoint {
            maxConnectionsPerRoute = 100
            pipelineMaxSize = 20
        }
    }
}

val apacheClient = HttpClient(Apache) {
    engine {
        followRedirects = true
        socketTimeout = 10_000
        connectTimeout = 10_000
        connectionRequestTimeout = 20_000
    }
}

// Use default engine
val defaultClient = HttpClient()  // Uses HttpClientEngineContainer.default

HttpClientEngineConfig

Base configuration class for all HTTP client engines.

/**
 * Base configuration for HTTP client engines
 */
open class HttpClientEngineConfig {
    /** Number of threads for the engine */
    var threadsCount: Int = 4
    
    /** Whether to enable HTTP pipelining */
    var pipelining: Boolean = false
    
    /** Proxy configuration */
    var proxy: ProxyConfig? = null
    
    /** Custom certificate verification */
    var https: HttpsConfig = HttpsConfig()
}

/**
 * HTTPS configuration
 */
class HttpsConfig {
    /** Trust all certificates (development only) */
    var trustManager: X509TrustManager? = null
    
    /** Custom SSL context */
    var sslContext: SSLContext? = null
    
    /** Hostname verifier */
    var hostnameVerifier: HostnameVerifier? = null
    
    /** Certificate pinning */
    var certificates: List<X509Certificate> = emptyList()
}

Engine Capabilities

System for declaring and checking engine capabilities.

/**
 * Represents a capability that an engine may support
 */
class HttpClientEngineCapability<T>(
    val key: String
) {
    override fun equals(other: Any?): Boolean
    override fun hashCode(): Int
    override fun toString(): String
}

/**
 * Check if engine supports a capability
 */
fun HttpClientEngine.supports(capability: HttpClientEngineCapability<*>): Boolean

/**
 * Get capability from engine if supported
 */
fun <T> HttpClientEngine.getCapability(capability: HttpClientEngineCapability<T>): T?

/**
 * Require capability from engine, throw if not supported
 */
fun <T> HttpClientEngine.requireCapability(capability: HttpClientEngineCapability<T>): T

Usage Examples:

// Define custom capability
val CompressionCapability = HttpClientEngineCapability<CompressionConfig>("compression")

// Check if engine supports capability
if (client.engine.supports(CompressionCapability)) {
    val compressionConfig = client.engine.getCapability(CompressionCapability)
    println("Compression supported with config: $compressionConfig")
}

// Require capability (throws if not supported)
try {
    val config = client.engine.requireCapability(CompressionCapability)
    // Use compression
} catch (e: IllegalStateException) {
    println("Engine does not support compression")
}

Engine-Specific Configurations

Configurations for different engine implementations.

/**
 * CIO engine configuration
 */
class CIOEngineConfig : HttpClientEngineConfig() {
    /** Maximum number of connections */
    var maxConnectionsCount: Int = 1000
    
    /** Endpoint configuration */
    val endpoint: EndpointConfig = EndpointConfig()
    
    /** Request timeout */
    var requestTimeout: Long = 15_000
}

class EndpointConfig {
    /** Maximum connections per route */
    var maxConnectionsPerRoute: Int = 100
    
    /** Pipeline maximum size */
    var pipelineMaxSize: Int = 20
    
    /** Keep alive time */
    var keepAliveTime: Long = 5000
    
    /** Connection idle timeout */
    var connectTimeout: Long = 5000
    
    /** Connection retry attempts */
    var connectAttempts: Int = 5
}

/**
 * Apache engine configuration
 */
class ApacheEngineConfig : HttpClientEngineConfig() {
    /** Follow redirects automatically */
    var followRedirects: Boolean = true
    
    /** Socket timeout */
    var socketTimeout: Int = 10_000
    
    /** Connection timeout */
    var connectTimeout: Int = 10_000
    
    /** Connection request timeout */
    var connectionRequestTimeout: Int = 20_000
    
    /** Custom request configuration */
    var customRequest: (RequestConfig.Builder.() -> Unit)? = null
}

/**
 * OkHttp engine configuration
 */
class OkHttpConfig : HttpClientEngineConfig() {
    /** Custom OkHttpClient instance */
    var preconfigured: OkHttpClient? = null
    
    /** OkHttp client configuration */
    var config: (OkHttpClient.Builder.() -> Unit)? = null
    
    /** WebSocket configuration */
    var webSocketFactory: WebSocket.Factory? = null
}

Usage Examples:

// CIO engine with detailed configuration
val cioClient = HttpClient(CIO) {
    engine {
        maxConnectionsCount = 2000
        requestTimeout = 30_000
        
        endpoint {
            maxConnectionsPerRoute = 200
            pipelineMaxSize = 50
            keepAliveTime = 10_000
            connectTimeout = 3_000
            connectAttempts = 3
        }
        
        https {
            trustManager = customTrustManager
        }
    }
}

// Apache engine configuration
val apacheClient = HttpClient(Apache) {
    engine {
        followRedirects = false
        socketTimeout = 15_000
        connectTimeout = 5_000
        connectionRequestTimeout = 10_000
        
        customRequest = {
            setCircularRedirectsAllowed(false)
            setRedirectsEnabled(false)
            setAuthenticationEnabled(true)
        }
    }
}

// OkHttp engine with custom client
val okHttpClient = OkHttpClient.Builder()
    .connectTimeout(10, TimeUnit.SECONDS)
    .readTimeout(30, TimeUnit.SECONDS)
    .addInterceptor(loggingInterceptor)
    .build()

val client = HttpClient(OkHttp) {
    engine {
        preconfigured = okHttpClient
    }
}

Engine Lifecycle

Manage engine lifecycle and resource cleanup.

/**
 * Engine lifecycle management
 */
interface EngineLifecycle {
    /** Initialize engine */
    suspend fun start()
    
    /** Shutdown engine gracefully */
    suspend fun shutdown()
    
    /** Force shutdown engine */
    suspend fun shutdownNow()
    
    /** Check if engine is running */
    val isRunning: Boolean
}

/**
 * Engine monitoring and metrics
 */
interface EngineMetrics {
    /** Active connections count */
    val activeConnections: Int
    
    /** Total requests made */
    val totalRequests: Long
    
    /** Failed requests count */
    val failedRequests: Long
    
    /** Average response time */
    val averageResponseTime: Double
}

Engine Selection

Utilities for engine selection and management.

/**
 * Engine selector for automatic engine selection
 */
object EngineSelector {
    /** Select best engine for current platform */
    fun selectDefault(): HttpClientEngineFactory<*>
    
    /** Select engine by name */
    fun selectByName(name: String): HttpClientEngineFactory<*>?
    
    /** Get available engines */
    fun getAvailableEngines(): List<HttpClientEngineFactory<*>>
}

/**
 * Platform-specific engine recommendations
 */
object PlatformEngines {
    /** Recommended engine for JVM */
    val JVM: HttpClientEngineFactory<*>
    
    /** Recommended engine for Android */
    val Android: HttpClientEngineFactory<*>
    
    /** Recommended engine for JavaScript */
    val JavaScript: HttpClientEngineFactory<*>
    
    /** Recommended engine for Native */
    val Native: HttpClientEngineFactory<*>
}

Engine Testing

Utilities for testing engine implementations.

/**
 * Mock engine for testing
 */
class MockEngine(
    val config: MockEngineConfig
) : HttpClientEngine {
    
    class MockEngineConfig : HttpClientEngineConfig() {
        /** Response handlers */
        val responseHandlers: MutableList<MockRequestHandler> = mutableListOf()
        
        /** Add response handler */
        fun addHandler(handler: MockRequestHandler)
        
        /** Add response handler with DSL */
        fun addHandler(block: MockRequestHandlerBuilder.() -> Unit)
    }
}

/**
 * Mock request handler
 */
class MockRequestHandler(
    val matcher: (HttpRequestData) -> Boolean,
    val responseBuilder: suspend MockRequestHandlerScope.(HttpRequestData) -> HttpResponseData
)

/**
 * Test engine utilities
 */
object TestEngineUtils {
    /** Create test engine with mock responses */
    fun createTestEngine(block: MockEngineConfig.() -> Unit): MockEngine
    
    /** Verify request expectations */
    fun verifyRequests(engine: MockEngine, expectations: List<RequestExpectation>)
}

Usage Examples:

// Mock engine for testing
val mockEngine = MockEngine {
    addHandler { request ->
        when (request.url.encodedPath) {
            "/users" -> respond(
                content = """[{"id": 1, "name": "John"}]""",
                status = HttpStatusCode.OK,
                headers = headersOf(HttpHeaders.ContentType, "application/json")
            )
            "/error" -> respond(
                content = "Not Found",
                status = HttpStatusCode.NotFound
            )
            else -> error("Unhandled request: ${request.url}")
        }
    }
}

val testClient = HttpClient(mockEngine)

// Test with mock engine
val response = testClient.get("/users")
assertEquals(HttpStatusCode.OK, response.status)

Types

// Engine data types
data class HttpRequestData(
    val url: Url,
    val method: HttpMethod,
    val headers: Headers,
    val body: OutgoingContent,
    val executionContext: Job,
    val attributes: Attributes
)

data class HttpResponseData(
    val statusCode: HttpStatusCode,
    val requestTime: GMTDate,
    val headers: Headers,
    val version: HttpProtocolVersion,
    val body: Any,
    val callContext: CoroutineContext
)

// Engine exception types
class UnsupportedEngineException(
    message: String
) : IllegalStateException(message)

class EngineClosedException(
    message: String = "Engine is closed"
) : IllegalStateException(message)

// Configuration types
data class ProxyConfig(
    val url: Url
) {
    constructor(host: String, port: Int) : this(
        URLBuilder().apply {
            this.host = host
            this.port = port
        }.build()
    )
    
    enum class Type {
        HTTP, HTTPS, SOCKS
    }
}

// Capability types
interface EngineCapabilityProvider {
    fun <T> provide(capability: HttpClientEngineCapability<T>): T?
}

// Engine factory registry
object EngineFactoryRegistry {
    fun register(name: String, factory: HttpClientEngineFactory<*>)
    fun unregister(name: String)
    fun get(name: String): HttpClientEngineFactory<*>?
    fun getAll(): Map<String, HttpClientEngineFactory<*>>
}

Install with Tessl CLI

npx tessl i tessl/maven-io-ktor--ktor-client-core-jvm

docs

client-configuration.md

content-handling.md

engine-architecture.md

events-monitoring.md

http-statement.md

index.md

plugin-system.md

request-building.md

response-handling.md

websocket-support.md

tile.json