0
# Engine Configuration
1
2
The HTTP engine abstraction layer provides pluggable HTTP implementations across platforms with comprehensive configuration options for connection management, proxies, and platform-specific settings.
3
4
## Core Engine Interface
5
6
```kotlin { .api }
7
interface HttpClientEngine : CoroutineScope, Closeable {
8
val config: HttpClientEngineConfig
9
val dispatcher: CoroutineDispatcher
10
val supportedCapabilities: Set<HttpClientEngineCapability<*>>
11
12
suspend fun execute(data: HttpRequestData): HttpResponseData
13
override fun close()
14
}
15
16
interface HttpClientEngineFactory<T : HttpClientEngineConfig> {
17
fun create(block: T.() -> Unit = {}): HttpClientEngine
18
}
19
20
abstract class HttpClientEngineBase(
21
engineName: String
22
) : HttpClientEngine {
23
protected val engine: String = engineName
24
protected abstract suspend fun execute(data: HttpRequestData): HttpResponseData
25
26
// Utility methods for subclasses
27
protected fun HttpRequestData.isUpgradeRequest(): Boolean
28
protected fun HttpRequestData.requiresDuplexConnection(): Boolean
29
}
30
```
31
32
## Engine Configuration
33
34
```kotlin { .api }
35
open class HttpClientEngineConfig {
36
var threadsCount: Int = 4
37
var pipelining: Boolean = false
38
var proxy: ProxyConfig? = null
39
40
// Connection settings
41
val requestsJob: CompletableJob = Job()
42
43
internal val clientConfig: HttpClientConfig<*>? = null
44
}
45
46
data class ProxyConfig(
47
val type: Type,
48
val address: SocketAddress
49
) {
50
enum class Type { HTTP, SOCKS }
51
52
companion object {
53
fun http(host: String, port: Int): ProxyConfig
54
fun socks(host: String, port: Int): ProxyConfig
55
}
56
}
57
```
58
59
## Engine Selection
60
61
### Platform Default Engines
62
```kotlin
63
// Uses platform-appropriate default engine
64
val client = HttpClient()
65
66
// Platform defaults:
67
// - JVM: CIO or OkHttp (if available)
68
// - JavaScript: Js (Fetch API)
69
// - Native: Curl
70
```
71
72
### Explicit Engine Selection
73
```kotlin
74
// Using specific engine factory
75
val client = HttpClient(engineFactory) {
76
// Engine-specific configuration
77
threadsCount = 8
78
pipelining = true
79
}
80
```
81
82
### Engine with Configuration
83
```kotlin
84
val client = HttpClient {
85
engine(engineFactory) {
86
// Engine configuration
87
threadsCount = 4
88
pipelining = false
89
90
// Proxy configuration
91
proxy = ProxyConfig.http("proxy.example.com", 8080)
92
}
93
}
94
```
95
96
## Proxy Configuration
97
98
### HTTP Proxy
99
```kotlin
100
val client = HttpClient {
101
engine(CIO) {
102
proxy = ProxyConfig.http("proxy.example.com", 8080)
103
}
104
}
105
```
106
107
### SOCKS Proxy
108
```kotlin
109
val client = HttpClient {
110
engine(CIO) {
111
proxy = ProxyConfig.socks("socks.example.com", 1080)
112
}
113
}
114
```
115
116
### No Proxy
117
```kotlin
118
val client = HttpClient {
119
engine(CIO) {
120
proxy = null // Disable proxy
121
}
122
}
123
```
124
125
## Engine Capabilities
126
127
```kotlin { .api }
128
interface HttpClientEngineCapability<T> {
129
val key: String
130
}
131
132
// Built-in capabilities
133
object HttpTimeoutCapability : HttpClientEngineCapability<HttpTimeoutConfig>
134
object WebSocketCapability : HttpClientEngineCapability<Unit>
135
object HttpRedirectCapability : HttpClientEngineCapability<HttpRedirect.Config>
136
```
137
138
### Checking Engine Capabilities
139
```kotlin
140
val engine = client.engine
141
142
if (WebSocketCapability in engine.supportedCapabilities) {
143
println("Engine supports WebSockets")
144
}
145
146
if (HttpTimeoutCapability in engine.supportedCapabilities) {
147
println("Engine supports timeouts")
148
}
149
```
150
151
## Connection Management
152
153
### Thread Pool Configuration
154
```kotlin
155
val client = HttpClient {
156
engine(CIO) {
157
// Set number of threads for connection pool
158
threadsCount = 8
159
160
// Enable HTTP pipelining
161
pipelining = true
162
}
163
}
164
```
165
166
### Connection Timeouts
167
Engine-specific timeout configuration:
168
169
```kotlin
170
val client = HttpClient {
171
engine(CIO) {
172
// CIO-specific timeouts
173
connectTimeout = 10000 // 10 seconds
174
requestTimeout = 30000 // 30 seconds
175
}
176
}
177
```
178
179
## Platform-Specific Engines
180
181
### JVM Platform
182
183
#### CIO Engine
184
```kotlin
185
val client = HttpClient(CIO) {
186
threadsCount = 4
187
pipelining = false
188
189
// CIO-specific settings
190
maxConnectionsCount = 1000
191
endpoint {
192
maxConnectionsPerRoute = 100
193
pipelineMaxSize = 20
194
keepAliveTime = 5000
195
connectTimeout = 5000
196
connectAttempts = 5
197
}
198
}
199
```
200
201
#### OkHttp Engine (if available)
202
```kotlin
203
val client = HttpClient(OkHttp) {
204
// OkHttp-specific configuration
205
config {
206
// Configure OkHttpClient
207
followRedirects(true)
208
connectTimeout(30, TimeUnit.SECONDS)
209
readTimeout(30, TimeUnit.SECONDS)
210
}
211
}
212
```
213
214
### JavaScript Platform
215
216
#### JS Engine (Fetch API)
217
```kotlin
218
val client = HttpClient(Js) {
219
// JS engine uses browser's fetch API
220
// Limited configuration options
221
}
222
```
223
224
### Native Platform
225
226
#### Curl Engine
227
```kotlin
228
val client = HttpClient(Curl) {
229
// Curl-specific configuration
230
sslOptions {
231
// SSL/TLS configuration
232
}
233
}
234
```
235
236
## Engine Lifecycle
237
238
### Manual Engine Management
239
```kotlin
240
val engine = engineFactory.create {
241
threadsCount = 4
242
pipelining = true
243
}
244
245
val client = HttpClient(engine)
246
247
// Manual cleanup
248
client.close()
249
engine.close()
250
```
251
252
### Shared Engine Instances
253
```kotlin
254
val sharedEngine = CIO.create {
255
threadsCount = 8
256
}
257
258
// Multiple clients can share the same engine
259
val client1 = HttpClient(sharedEngine)
260
val client2 = HttpClient(sharedEngine)
261
262
// Only close engine after all clients are closed
263
client1.close()
264
client2.close()
265
sharedEngine.close()
266
```
267
268
## Engine Utils
269
270
```kotlin { .api }
271
// Engine utility functions
272
fun HttpClientEngineConfig.proxy(type: ProxyConfig.Type, host: String, port: Int)
273
274
// Request data utilities
275
fun HttpRequestData.isWebSocketRequest(): Boolean
276
fun HttpRequestData.isUpgradeRequest(): Boolean
277
278
// Response data utilities
279
class HttpResponseData(
280
val statusCode: HttpStatusCode,
281
val requestTime: GMTDate,
282
val headers: Headers,
283
val version: HttpProtocolVersion,
284
val body: ByteReadChannel,
285
val callContext: CoroutineContext
286
)
287
```
288
289
## Custom Engine Implementation
290
291
### Basic Custom Engine
292
```kotlin
293
class MyCustomEngine(
294
override val config: MyCustomEngineConfig
295
) : HttpClientEngineBase("MyCustomEngine") {
296
297
override val dispatcher: CoroutineDispatcher = Dispatchers.IO
298
299
override suspend fun execute(data: HttpRequestData): HttpResponseData {
300
// Custom HTTP implementation
301
return HttpResponseData(
302
statusCode = HttpStatusCode.OK,
303
requestTime = GMTDate(),
304
headers = Headers.Empty,
305
version = HttpProtocolVersion.HTTP_1_1,
306
body = ByteReadChannel.Empty,
307
callContext = coroutineContext
308
)
309
}
310
311
override fun close() {
312
// Cleanup resources
313
}
314
}
315
316
class MyCustomEngineConfig : HttpClientEngineConfig() {
317
// Custom configuration properties
318
var customProperty: String = "default"
319
}
320
321
object MyCustomEngineFactory : HttpClientEngineFactory<MyCustomEngineConfig> {
322
override fun create(block: MyCustomEngineConfig.() -> Unit): HttpClientEngine {
323
val config = MyCustomEngineConfig().apply(block)
324
return MyCustomEngine(config)
325
}
326
}
327
```
328
329
### Using Custom Engine
330
```kotlin
331
val client = HttpClient(MyCustomEngineFactory) {
332
customProperty = "custom value"
333
threadsCount = 2
334
}
335
```
336
337
## Engine Testing
338
339
### Mock Engine for Testing
340
```kotlin
341
val mockEngine = MockEngine { request ->
342
respond(
343
content = """{"id": 1, "name": "John"}""",
344
status = HttpStatusCode.OK,
345
headers = headersOf(HttpHeaders.ContentType, "application/json")
346
)
347
}
348
349
val client = HttpClient(mockEngine)
350
val response = client.get("http://test.com/users/1")
351
// Response will be the mocked data
352
```
353
354
## Error Handling
355
356
### Engine-Specific Errors
357
```kotlin
358
try {
359
val response = client.get("https://example.com")
360
} catch (e: ConnectTimeoutException) {
361
println("Connection timeout")
362
} catch (e: SocketTimeoutException) {
363
println("Read timeout")
364
} catch (e: UnresolvedAddressException) {
365
println("DNS resolution failed")
366
} catch (e: ConnectException) {
367
println("Connection failed")
368
}
369
```
370
371
### Engine Capability Errors
372
```kotlin
373
try {
374
client.webSocket("wss://example.com/ws") {
375
// WebSocket code
376
}
377
} catch (e: UnsupportedOperationException) {
378
println("Current engine doesn't support WebSockets")
379
}
380
```