or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-configuration.mdcontent-handling.mdengine-architecture.mdevents-monitoring.mdhttp-statement.mdindex.mdplugin-system.mdrequest-building.mdresponse-handling.mdwebsocket-support.md

engine-architecture.mddocs/

0

# Engine Architecture

1

2

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

3

4

## Capabilities

5

6

### HttpClientEngine Interface

7

8

Core engine interface that all HTTP client implementations must implement.

9

10

```kotlin { .api }

11

/**

12

* HTTP client engine interface

13

*/

14

interface HttpClientEngine : CoroutineScope, Closeable {

15

/** Engine configuration */

16

val config: HttpClientEngineConfig

17

18

/** Coroutine dispatcher for engine operations */

19

val dispatcher: CoroutineDispatcher

20

21

/** Set of capabilities supported by this engine */

22

val supportedCapabilities: Set<HttpClientEngineCapability<*>>

23

24

/** Execute HTTP request and return response data */

25

suspend fun execute(data: HttpRequestData): HttpResponseData

26

27

/** Install engine in HTTP client */

28

fun install(client: HttpClient)

29

30

/** Close engine and release resources */

31

override fun close()

32

}

33

```

34

35

### HttpClientEngineFactory

36

37

Factory interface for creating engine instances.

38

39

```kotlin { .api }

40

/**

41

* Factory for creating HTTP client engines

42

*/

43

interface HttpClientEngineFactory<T : HttpClientEngineConfig> {

44

/** Create engine instance with configuration */

45

fun create(block: T.() -> Unit = {}): HttpClientEngine

46

}

47

48

/**

49

* Engine container for default engine selection

50

*/

51

object HttpClientEngineContainer {

52

/** Default engine for current platform */

53

val default: HttpClientEngine

54

55

/** Install engine factory */

56

fun install(factory: HttpClientEngineFactory<*>)

57

}

58

```

59

60

**Usage Examples:**

61

62

```kotlin

63

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

64

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

65

66

// Create client with specific engine

67

val cioClient = HttpClient(CIO) {

68

engine {

69

maxConnectionsCount = 1000

70

endpoint {

71

maxConnectionsPerRoute = 100

72

pipelineMaxSize = 20

73

}

74

}

75

}

76

77

val apacheClient = HttpClient(Apache) {

78

engine {

79

followRedirects = true

80

socketTimeout = 10_000

81

connectTimeout = 10_000

82

connectionRequestTimeout = 20_000

83

}

84

}

85

86

// Use default engine

87

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

88

```

89

90

### HttpClientEngineConfig

91

92

Base configuration class for all HTTP client engines.

93

94

```kotlin { .api }

95

/**

96

* Base configuration for HTTP client engines

97

*/

98

open class HttpClientEngineConfig {

99

/** Number of threads for the engine */

100

var threadsCount: Int = 4

101

102

/** Whether to enable HTTP pipelining */

103

var pipelining: Boolean = false

104

105

/** Proxy configuration */

106

var proxy: ProxyConfig? = null

107

108

/** Custom certificate verification */

109

var https: HttpsConfig = HttpsConfig()

110

}

111

112

/**

113

* HTTPS configuration

114

*/

115

class HttpsConfig {

116

/** Trust all certificates (development only) */

117

var trustManager: X509TrustManager? = null

118

119

/** Custom SSL context */

120

var sslContext: SSLContext? = null

121

122

/** Hostname verifier */

123

var hostnameVerifier: HostnameVerifier? = null

124

125

/** Certificate pinning */

126

var certificates: List<X509Certificate> = emptyList()

127

}

128

```

129

130

### Engine Capabilities

131

132

System for declaring and checking engine capabilities.

133

134

```kotlin { .api }

135

/**

136

* Represents a capability that an engine may support

137

*/

138

class HttpClientEngineCapability<T>(

139

val key: String

140

) {

141

override fun equals(other: Any?): Boolean

142

override fun hashCode(): Int

143

override fun toString(): String

144

}

145

146

/**

147

* Check if engine supports a capability

148

*/

149

fun HttpClientEngine.supports(capability: HttpClientEngineCapability<*>): Boolean

150

151

/**

152

* Get capability from engine if supported

153

*/

154

fun <T> HttpClientEngine.getCapability(capability: HttpClientEngineCapability<T>): T?

155

156

/**

157

* Require capability from engine, throw if not supported

158

*/

159

fun <T> HttpClientEngine.requireCapability(capability: HttpClientEngineCapability<T>): T

160

```

161

162

**Usage Examples:**

163

164

```kotlin

165

// Define custom capability

166

val CompressionCapability = HttpClientEngineCapability<CompressionConfig>("compression")

167

168

// Check if engine supports capability

169

if (client.engine.supports(CompressionCapability)) {

170

val compressionConfig = client.engine.getCapability(CompressionCapability)

171

println("Compression supported with config: $compressionConfig")

172

}

173

174

// Require capability (throws if not supported)

175

try {

176

val config = client.engine.requireCapability(CompressionCapability)

177

// Use compression

178

} catch (e: IllegalStateException) {

179

println("Engine does not support compression")

180

}

181

```

182

183

### Engine-Specific Configurations

184

185

Configurations for different engine implementations.

186

187

```kotlin { .api }

188

/**

189

* CIO engine configuration

190

*/

191

class CIOEngineConfig : HttpClientEngineConfig() {

192

/** Maximum number of connections */

193

var maxConnectionsCount: Int = 1000

194

195

/** Endpoint configuration */

196

val endpoint: EndpointConfig = EndpointConfig()

197

198

/** Request timeout */

199

var requestTimeout: Long = 15_000

200

}

201

202

class EndpointConfig {

203

/** Maximum connections per route */

204

var maxConnectionsPerRoute: Int = 100

205

206

/** Pipeline maximum size */

207

var pipelineMaxSize: Int = 20

208

209

/** Keep alive time */

210

var keepAliveTime: Long = 5000

211

212

/** Connection idle timeout */

213

var connectTimeout: Long = 5000

214

215

/** Connection retry attempts */

216

var connectAttempts: Int = 5

217

}

218

219

/**

220

* Apache engine configuration

221

*/

222

class ApacheEngineConfig : HttpClientEngineConfig() {

223

/** Follow redirects automatically */

224

var followRedirects: Boolean = true

225

226

/** Socket timeout */

227

var socketTimeout: Int = 10_000

228

229

/** Connection timeout */

230

var connectTimeout: Int = 10_000

231

232

/** Connection request timeout */

233

var connectionRequestTimeout: Int = 20_000

234

235

/** Custom request configuration */

236

var customRequest: (RequestConfig.Builder.() -> Unit)? = null

237

}

238

239

/**

240

* OkHttp engine configuration

241

*/

242

class OkHttpConfig : HttpClientEngineConfig() {

243

/** Custom OkHttpClient instance */

244

var preconfigured: OkHttpClient? = null

245

246

/** OkHttp client configuration */

247

var config: (OkHttpClient.Builder.() -> Unit)? = null

248

249

/** WebSocket configuration */

250

var webSocketFactory: WebSocket.Factory? = null

251

}

252

```

253

254

**Usage Examples:**

255

256

```kotlin

257

// CIO engine with detailed configuration

258

val cioClient = HttpClient(CIO) {

259

engine {

260

maxConnectionsCount = 2000

261

requestTimeout = 30_000

262

263

endpoint {

264

maxConnectionsPerRoute = 200

265

pipelineMaxSize = 50

266

keepAliveTime = 10_000

267

connectTimeout = 3_000

268

connectAttempts = 3

269

}

270

271

https {

272

trustManager = customTrustManager

273

}

274

}

275

}

276

277

// Apache engine configuration

278

val apacheClient = HttpClient(Apache) {

279

engine {

280

followRedirects = false

281

socketTimeout = 15_000

282

connectTimeout = 5_000

283

connectionRequestTimeout = 10_000

284

285

customRequest = {

286

setCircularRedirectsAllowed(false)

287

setRedirectsEnabled(false)

288

setAuthenticationEnabled(true)

289

}

290

}

291

}

292

293

// OkHttp engine with custom client

294

val okHttpClient = OkHttpClient.Builder()

295

.connectTimeout(10, TimeUnit.SECONDS)

296

.readTimeout(30, TimeUnit.SECONDS)

297

.addInterceptor(loggingInterceptor)

298

.build()

299

300

val client = HttpClient(OkHttp) {

301

engine {

302

preconfigured = okHttpClient

303

}

304

}

305

```

306

307

### Engine Lifecycle

308

309

Manage engine lifecycle and resource cleanup.

310

311

```kotlin { .api }

312

/**

313

* Engine lifecycle management

314

*/

315

interface EngineLifecycle {

316

/** Initialize engine */

317

suspend fun start()

318

319

/** Shutdown engine gracefully */

320

suspend fun shutdown()

321

322

/** Force shutdown engine */

323

suspend fun shutdownNow()

324

325

/** Check if engine is running */

326

val isRunning: Boolean

327

}

328

329

/**

330

* Engine monitoring and metrics

331

*/

332

interface EngineMetrics {

333

/** Active connections count */

334

val activeConnections: Int

335

336

/** Total requests made */

337

val totalRequests: Long

338

339

/** Failed requests count */

340

val failedRequests: Long

341

342

/** Average response time */

343

val averageResponseTime: Double

344

}

345

```

346

347

### Engine Selection

348

349

Utilities for engine selection and management.

350

351

```kotlin { .api }

352

/**

353

* Engine selector for automatic engine selection

354

*/

355

object EngineSelector {

356

/** Select best engine for current platform */

357

fun selectDefault(): HttpClientEngineFactory<*>

358

359

/** Select engine by name */

360

fun selectByName(name: String): HttpClientEngineFactory<*>?

361

362

/** Get available engines */

363

fun getAvailableEngines(): List<HttpClientEngineFactory<*>>

364

}

365

366

/**

367

* Platform-specific engine recommendations

368

*/

369

object PlatformEngines {

370

/** Recommended engine for JVM */

371

val JVM: HttpClientEngineFactory<*>

372

373

/** Recommended engine for Android */

374

val Android: HttpClientEngineFactory<*>

375

376

/** Recommended engine for JavaScript */

377

val JavaScript: HttpClientEngineFactory<*>

378

379

/** Recommended engine for Native */

380

val Native: HttpClientEngineFactory<*>

381

}

382

```

383

384

### Engine Testing

385

386

Utilities for testing engine implementations.

387

388

```kotlin { .api }

389

/**

390

* Mock engine for testing

391

*/

392

class MockEngine(

393

val config: MockEngineConfig

394

) : HttpClientEngine {

395

396

class MockEngineConfig : HttpClientEngineConfig() {

397

/** Response handlers */

398

val responseHandlers: MutableList<MockRequestHandler> = mutableListOf()

399

400

/** Add response handler */

401

fun addHandler(handler: MockRequestHandler)

402

403

/** Add response handler with DSL */

404

fun addHandler(block: MockRequestHandlerBuilder.() -> Unit)

405

}

406

}

407

408

/**

409

* Mock request handler

410

*/

411

class MockRequestHandler(

412

val matcher: (HttpRequestData) -> Boolean,

413

val responseBuilder: suspend MockRequestHandlerScope.(HttpRequestData) -> HttpResponseData

414

)

415

416

/**

417

* Test engine utilities

418

*/

419

object TestEngineUtils {

420

/** Create test engine with mock responses */

421

fun createTestEngine(block: MockEngineConfig.() -> Unit): MockEngine

422

423

/** Verify request expectations */

424

fun verifyRequests(engine: MockEngine, expectations: List<RequestExpectation>)

425

}

426

```

427

428

**Usage Examples:**

429

430

```kotlin

431

// Mock engine for testing

432

val mockEngine = MockEngine {

433

addHandler { request ->

434

when (request.url.encodedPath) {

435

"/users" -> respond(

436

content = """[{"id": 1, "name": "John"}]""",

437

status = HttpStatusCode.OK,

438

headers = headersOf(HttpHeaders.ContentType, "application/json")

439

)

440

"/error" -> respond(

441

content = "Not Found",

442

status = HttpStatusCode.NotFound

443

)

444

else -> error("Unhandled request: ${request.url}")

445

}

446

}

447

}

448

449

val testClient = HttpClient(mockEngine)

450

451

// Test with mock engine

452

val response = testClient.get("/users")

453

assertEquals(HttpStatusCode.OK, response.status)

454

```

455

456

## Types

457

458

```kotlin { .api }

459

// Engine data types

460

data class HttpRequestData(

461

val url: Url,

462

val method: HttpMethod,

463

val headers: Headers,

464

val body: OutgoingContent,

465

val executionContext: Job,

466

val attributes: Attributes

467

)

468

469

data class HttpResponseData(

470

val statusCode: HttpStatusCode,

471

val requestTime: GMTDate,

472

val headers: Headers,

473

val version: HttpProtocolVersion,

474

val body: Any,

475

val callContext: CoroutineContext

476

)

477

478

// Engine exception types

479

class UnsupportedEngineException(

480

message: String

481

) : IllegalStateException(message)

482

483

class EngineClosedException(

484

message: String = "Engine is closed"

485

) : IllegalStateException(message)

486

487

// Configuration types

488

data class ProxyConfig(

489

val url: Url

490

) {

491

constructor(host: String, port: Int) : this(

492

URLBuilder().apply {

493

this.host = host

494

this.port = port

495

}.build()

496

)

497

498

enum class Type {

499

HTTP, HTTPS, SOCKS

500

}

501

}

502

503

// Capability types

504

interface EngineCapabilityProvider {

505

fun <T> provide(capability: HttpClientEngineCapability<T>): T?

506

}

507

508

// Engine factory registry

509

object EngineFactoryRegistry {

510

fun register(name: String, factory: HttpClientEngineFactory<*>)

511

fun unregister(name: String)

512

fun get(name: String): HttpClientEngineFactory<*>?

513

fun getAll(): Map<String, HttpClientEngineFactory<*>>

514

}

515

```