A multiplatform asynchronous framework for creating microservices, web applications, and HTTP clients written in Kotlin from the ground up
—
HTTP client engines for different platforms and engine configuration options that provide the underlying HTTP implementation.
Core interface for HTTP client engines that handle the actual HTTP communication.
/**
* HTTP client engine interface for platform-specific HTTP implementations
*/
interface HttpClientEngine : CoroutineScope, Closeable {
/** Coroutine dispatcher for engine operations */
val dispatcher: CoroutineDispatcher
/** Engine configuration */
val config: HttpClientEngineConfig
/** Set of capabilities supported by this engine */
val supportedCapabilities: Set<HttpClientEngineCapability<*>>
/**
* Execute an HTTP request
* @param data Request data to execute
* @return Response data from server
*/
suspend fun execute(data: HttpRequestData): HttpResponseData
/**
* Install the engine with a client
* @param client HttpClient instance using this engine
*/
fun install(client: HttpClient)
}Factory interface for creating engine instances with configuration.
/**
* Factory for creating HTTP client engines
*/
interface HttpClientEngineFactory<out T : HttpClientEngineConfig> {
/**
* Create an engine instance with configuration
* @param block Configuration block for the engine
* @return Configured engine instance
*/
fun create(block: T.() -> Unit = {}): HttpClientEngine
}Usage Examples:
import io.ktor.client.*
import io.ktor.client.engine.cio.*
// Create client with specific engine factory
val client = HttpClient(CIO) {
engine {
threadsCount = 4
pipelining = true
}
}
// Create engine directly
val engine = CIO.create {
threadsCount = 2
pipelining = false
}
val client2 = HttpClient(engine)Base configuration class for HTTP client engines.
/**
* Base configuration for HTTP client engines
*/
open class HttpClientEngineConfig {
/** Coroutine dispatcher for engine operations, null for default */
var dispatcher: CoroutineDispatcher? = null
/** Whether to enable HTTP pipelining */
var pipelining: Boolean = false
/** Number of threads to use for HTTP operations */
var threadsCount: Int = 4
/** Proxy configuration */
var proxy: ProxyConfig? = null
}Usage Examples:
import io.ktor.client.*
import io.ktor.client.engine.cio.*
import kotlinx.coroutines.Dispatchers
val client = HttpClient(CIO) {
engine {
// Configure dispatcher
dispatcher = Dispatchers.IO
// Enable pipelining for better performance
pipelining = true
// Set thread count
threadsCount = 8
// Configure proxy if needed
proxy = ProxyBuilder.http("http://proxy.example.com:8080")
}
}System for declaring and checking engine capabilities.
/**
* Marker interface for engine capabilities
*/
interface HttpClientEngineCapability<T : Any>
/**
* WebSocket capability marker
*/
data object WebSocketCapability : HttpClientEngineCapability<Unit>
/**
* Server-Sent Events capability marker
*/
data object SSECapability : HttpClientEngineCapability<Unit>Usage Examples:
import io.ktor.client.*
import io.ktor.client.engine.*
val client = HttpClient()
// Check if engine supports WebSockets
if (client.isSupported(WebSocketCapability)) {
// Use WebSocket functionality
client.webSocket("wss://example.com/ws") {
// WebSocket operations
}
}
// Check if engine supports Server-Sent Events
if (client.isSupported(SSECapability)) {
// Use SSE functionality
client.sse("https://example.com/events") {
// SSE operations
}
}Data class representing the raw response data from an engine.
/**
* Raw HTTP response data from engine
*/
class HttpResponseData(
val statusCode: HttpStatusCode,
val requestTime: GMTDate,
val headers: Headers,
val version: HttpProtocolVersion,
val body: Any,
val callContext: CoroutineContext
) {
/** Timestamp when response was received */
val responseTime: GMTDate = GMTDate.now()
}Configuration classes for HTTP proxy support.
/**
* Proxy configuration
*/
sealed class ProxyConfig {
abstract val url: Url
}
/**
* HTTP proxy configuration
*/
class ProxyBuilder {
companion object {
/**
* Create HTTP proxy configuration
* @param url Proxy URL
* @return ProxyConfig for HTTP proxy
*/
fun http(url: String): ProxyConfig
/**
* Create SOCKS proxy configuration
* @param host Proxy host
* @param port Proxy port
* @return ProxyConfig for SOCKS proxy
*/
fun socks(host: String, port: Int): ProxyConfig
}
}Usage Examples:
import io.ktor.client.*
import io.ktor.client.engine.cio.*
val client = HttpClient(CIO) {
engine {
// HTTP proxy
proxy = ProxyBuilder.http("http://proxy.example.com:8080")
// SOCKS proxy
proxy = ProxyBuilder.socks("socks.example.com", 1080)
}
}Available engines for JVM platform:
/**
* CIO engine factory for JVM (Coroutine-based I/O)
*/
object CIO : HttpClientEngineFactory<CIOEngineConfig>
/**
* Apache HTTP client engine factory
*/
object Apache : HttpClientEngineFactory<ApacheEngineConfig>
/**
* Java HTTP client engine factory (Java 11+)
*/
object Java : HttpClientEngineFactory<JavaHttpConfig>
/**
* Jetty HTTP client engine factory
*/
object Jetty : HttpClientEngineFactory<JettyEngineConfig>
/**
* OkHttp engine factory
*/
object OkHttp : HttpClientEngineFactory<OkHttpConfig>Available engines for JavaScript platform:
/**
* JavaScript engine using browser APIs
*/
object Js : HttpClientEngineFactory<HttpClientEngineConfig>
/**
* Fetch API engine for modern browsers
*/
object JsFetch : HttpClientEngineFactory<HttpClientEngineConfig>Available engines for Native platforms:
/**
* Native engine using platform-specific HTTP implementations
*/
object Native : HttpClientEngineFactory<HttpClientEngineConfig>
/**
* WinHttp engine for Windows Native
*/
object WinHttp : HttpClientEngineFactory<WinHttpEngineConfig>
/**
* Darwin engine for iOS/macOS Native
*/
object Darwin : HttpClientEngineFactory<DarwinEngineConfig>Usage Examples:
// JVM - CIO engine
val cioClient = HttpClient(CIO) {
engine {
threadsCount = 4
pipelining = true
}
}
// JVM - Apache engine
val apacheClient = HttpClient(Apache) {
engine {
threadsCount = 8
followRedirects = true
}
}
// JavaScript - Fetch API
val jsClient = HttpClient(JsFetch)
// Native - Darwin engine (iOS/macOS)
val darwinClient = HttpClient(Darwin) {
engine {
configureRequest {
setAllowsCellularAccess(false)
}
}
}Exceptions specific to engine operations:
/**
* Thrown when engine is already closed
*/
class ClientEngineClosedException : IllegalStateException()
/**
* Thrown when using unsafe headers
*/
class UnsafeHeaderException(header: String) : IllegalArgumentException()
/**
* Connection timeout exception
*/
class ConnectTimeoutException(
message: String,
cause: Throwable? = null
) : IOException(message, cause)
/**
* Socket timeout exception
*/
class SocketTimeoutException(
message: String,
cause: Throwable? = null
) : IOException(message, cause)Usage Examples:
import io.ktor.client.*
import io.ktor.client.engine.*
import io.ktor.client.request.*
val client = HttpClient()
try {
val response = client.get("https://slow-api.example.com")
} catch (e: ConnectTimeoutException) {
println("Connection timeout: ${e.message}")
} catch (e: SocketTimeoutException) {
println("Socket timeout: ${e.message}")
} catch (e: ClientEngineClosedException) {
println("Engine was closed")
} finally {
client.close()
}Engine system related types:
/**
* Attribute key for engine capabilities
*/
val ENGINE_CAPABILITIES_KEY: AttributeKey<MutableMap<HttpClientEngineCapability<*>, Any>>
/**
* Outgoing content types for request bodies
*/
sealed class OutgoingContent {
abstract class ByteArrayContent : OutgoingContent()
abstract class ReadChannelContent : OutgoingContent()
abstract class WriteChannelContent : OutgoingContent()
abstract class ProtocolUpgrade : OutgoingContent()
abstract class NoContent : OutgoingContent()
}
/**
* Content type representation
*/
data class ContentType(
val contentType: String,
val contentSubtype: String,
val parameters: List<HeaderValueParam>
) {
companion object {
val Any = ContentType("*", "*")
object Application {
val Json = ContentType("application", "json")
val Xml = ContentType("application", "xml")
val FormUrlEncoded = ContentType("application", "x-www-form-urlencoded")
val OctetStream = ContentType("application", "octet-stream")
}
object Text {
val Plain = ContentType("text", "plain")
val Html = ContentType("text", "html")
val CSS = ContentType("text", "css")
}
object Image {
val PNG = ContentType("image", "png")
val JPEG = ContentType("image", "jpeg")
val GIF = ContentType("image", "gif")
}
object MultiPart {
val FormData = ContentType("multipart", "form-data")
val Mixed = ContentType("multipart", "mixed")
}
}
fun match(other: ContentType): Boolean
fun withParameter(name: String, value: String): ContentType
}Install with Tessl CLI
npx tessl i tessl/maven-io-ktor--ktor