or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

built-in-plugins.mdengine-configuration.mdform-data-content.mdhttp-client.mdindex.mdplugin-system.mdrequest-building.mdresponse-handling.md

built-in-plugins.mddocs/

0

# Built-in Plugins and Features

1

2

Comprehensive set of built-in plugins providing essential HTTP client features including authentication, cookies, redirects, timeouts, content negotiation, and WebSocket support.

3

4

## Core Plugins

5

6

### HttpRequestLifecycle

7

8

Core plugin for managing request lifecycle events.

9

10

```kotlin { .api }

11

/**

12

* Plugin for managing HTTP request lifecycle events

13

*/

14

object HttpRequestLifecycle : HttpClientPlugin<Unit, Unit>

15

```

16

17

### BodyProgress

18

19

Plugin for tracking upload and download progress.

20

21

```kotlin { .api }

22

/**

23

* Plugin for tracking request/response body progress

24

*/

25

object BodyProgress : HttpClientPlugin<Unit, Unit>

26

```

27

28

### SaveBody

29

30

Plugin for saving response bodies for multiple access.

31

32

```kotlin { .api }

33

/**

34

* Plugin for saving response bodies to enable multiple reads

35

*/

36

object SaveBody : HttpClientPlugin<Unit, Unit>

37

```

38

39

## Authentication

40

41

### Auth Plugin

42

43

Comprehensive authentication plugin supporting multiple authentication schemes.

44

45

```kotlin { .api }

46

/**

47

* Authentication plugin supporting multiple auth providers

48

*/

49

object Auth : HttpClientPlugin<AuthConfig, Auth> {

50

/** Install bearer token authentication */

51

fun AuthConfig.bearer(block: BearerAuthConfig.() -> Unit)

52

53

/** Install basic authentication */

54

fun AuthConfig.basic(block: BasicAuthConfig.() -> Unit)

55

56

/** Install digest authentication */

57

fun AuthConfig.digest(block: DigestAuthConfig.() -> Unit)

58

59

/** Install OAuth authentication */

60

fun AuthConfig.oauth(block: OAuthConfig.() -> Unit)

61

}

62

63

/**

64

* Bearer token authentication configuration

65

*/

66

class BearerAuthConfig {

67

/** Load tokens for authentication */

68

fun loadTokens(block: suspend () -> BearerTokens?)

69

70

/** Refresh tokens when expired */

71

fun refreshTokens(block: suspend (BearerTokens) -> BearerTokens?)

72

73

/** Send credentials without waiting for 401 */

74

var sendWithoutRequest: Boolean

75

76

/** Realm for authentication */

77

var realm: String?

78

}

79

80

/**

81

* Bearer tokens for OAuth-style authentication

82

*/

83

data class BearerTokens(

84

val accessToken: String,

85

val refreshToken: String?

86

)

87

88

/**

89

* Basic authentication configuration

90

*/

91

class BasicAuthConfig {

92

/** Username for authentication */

93

var username: String

94

95

/** Password for authentication */

96

var password: String

97

98

/** Send credentials without waiting for 401 */

99

var sendWithoutRequest: Boolean

100

101

/** Realm for authentication */

102

var realm: String?

103

}

104

```

105

106

**Usage Examples:**

107

108

```kotlin

109

import io.ktor.client.*

110

import io.ktor.client.plugins.auth.*

111

import io.ktor.client.plugins.auth.providers.*

112

113

// Bearer token authentication

114

val bearerClient = HttpClient {

115

install(Auth) {

116

bearer {

117

loadTokens {

118

// Load tokens from storage

119

BearerTokens(

120

accessToken = "your_access_token",

121

refreshToken = "your_refresh_token"

122

)

123

}

124

125

refreshTokens { tokens ->

126

// Refresh expired tokens

127

val response = client.post("https://auth.example.com/refresh") {

128

setBody("""{"refresh_token": "${tokens.refreshToken}"}""")

129

}

130

val newTokens = response.body<TokenResponse>()

131

BearerTokens(newTokens.accessToken, newTokens.refreshToken)

132

}

133

134

sendWithoutRequest = false

135

realm = "api"

136

}

137

}

138

}

139

140

// Basic authentication

141

val basicClient = HttpClient {

142

install(Auth) {

143

basic {

144

username = "user"

145

password = "password"

146

sendWithoutRequest = true

147

realm = null

148

}

149

}

150

}

151

152

// Multiple auth providers

153

val multiAuthClient = HttpClient {

154

install(Auth) {

155

basic {

156

username = "api_user"

157

password = "api_password"

158

realm = "api"

159

}

160

161

bearer {

162

loadTokens { bearerTokens }

163

realm = "oauth"

164

}

165

}

166

}

167

```

168

169

## Cookie Management

170

171

### HttpCookies Plugin

172

173

Automatic cookie handling with customizable storage.

174

175

```kotlin { .api }

176

/**

177

* HTTP cookies plugin for automatic cookie management

178

*/

179

object HttpCookies : HttpClientPlugin<HttpCookiesConfig, HttpCookies>

180

181

/**

182

* Cookie configuration

183

*/

184

class HttpCookiesConfig {

185

/** Cookie storage implementation */

186

var storage: CookiesStorage = AcceptAllCookiesStorage()

187

}

188

189

/**

190

* Cookie storage interface

191

*/

192

interface CookiesStorage {

193

/** Get cookies for specific URL */

194

suspend fun get(requestUrl: Url): List<Cookie>

195

196

/** Add cookie received from response */

197

suspend fun addCookie(requestUrl: Url, cookie: Cookie)

198

199

/** Close storage and cleanup resources */

200

fun close()

201

}

202

203

/**

204

* Cookie storage that accepts all cookies

205

*/

206

class AcceptAllCookiesStorage : CookiesStorage

207

208

/**

209

* Cookie representation

210

*/

211

data class Cookie(

212

val name: String,

213

val value: String,

214

val encoding: CookieEncoding = CookieEncoding.URI_ENCODING,

215

val maxAge: Int = 0,

216

val expires: GMTDate? = null,

217

val domain: String? = null,

218

val path: String? = null,

219

val secure: Boolean = false,

220

val httpOnly: Boolean = false,

221

val extensions: Map<String, String?> = emptyMap()

222

)

223

224

/** Get cookies for specific URL */

225

suspend fun HttpClient.cookies(url: String): List<Cookie>

226

```

227

228

**Usage Examples:**

229

230

```kotlin

231

import io.ktor.client.*

232

import io.ktor.client.plugins.cookies.*

233

234

// Basic cookie handling

235

val cookieClient = HttpClient {

236

install(HttpCookies) {

237

storage = AcceptAllCookiesStorage()

238

}

239

}

240

241

// Custom cookie storage

242

class CustomCookieStorage : CookiesStorage {

243

private val cookies = mutableMapOf<String, MutableList<Cookie>>()

244

245

override suspend fun get(requestUrl: Url): List<Cookie> {

246

return cookies[requestUrl.host] ?: emptyList()

247

}

248

249

override suspend fun addCookie(requestUrl: Url, cookie: Cookie) {

250

cookies.getOrPut(requestUrl.host) { mutableListOf() }.add(cookie)

251

}

252

253

override fun close() {

254

cookies.clear()

255

}

256

}

257

258

val customCookieClient = HttpClient {

259

install(HttpCookies) {

260

storage = CustomCookieStorage()

261

}

262

}

263

264

// Access cookies

265

val cookies = cookieClient.cookies("https://example.com")

266

cookies.forEach { cookie ->

267

println("Cookie: ${cookie.name}=${cookie.value}")

268

}

269

```

270

271

## Request/Response Processing

272

273

### HttpRedirect Plugin

274

275

Automatic handling of HTTP redirects.

276

277

```kotlin { .api }

278

/**

279

* Plugin for automatic HTTP redirect handling

280

*/

281

object HttpRedirect : HttpClientPlugin<Unit, Unit>

282

```

283

284

### HttpCallValidator Plugin

285

286

Response validation and error handling.

287

288

```kotlin { .api }

289

/**

290

* Plugin for HTTP call validation and error handling

291

*/

292

object HttpCallValidator : HttpClientPlugin<Unit, Unit>

293

```

294

295

### HttpPlainText Plugin

296

297

Plain text content transformation.

298

299

```kotlin { .api }

300

/**

301

* Plugin for plain text content transformation

302

*/

303

object HttpPlainText : HttpClientPlugin<Unit, Unit>

304

```

305

306

### DefaultRequest Plugin

307

308

Sets default request parameters for all requests including base URL and common headers.

309

310

```kotlin { .api }

311

/**

312

* Plugin for setting default request parameters including base URL and headers

313

*/

314

object DefaultRequest : HttpClientPlugin<DefaultRequestConfig, Unit>

315

316

/**

317

* Default request configuration

318

*/

319

class DefaultRequestConfig {

320

/** Configure default URL */

321

fun url(block: URLBuilder.() -> Unit)

322

323

/** Configure default headers */

324

fun headers(block: HeadersBuilder.() -> Unit)

325

326

/** Set default header value */

327

fun header(key: String, value: String)

328

}

329

```

330

331

**Usage Examples:**

332

333

```kotlin

334

import io.ktor.client.*

335

import io.ktor.client.plugins.*

336

337

// Set default base URL and headers

338

val client = HttpClient {

339

install(DefaultRequest) {

340

url {

341

protocol = URLProtocol.HTTPS

342

host = "api.example.com"

343

path("v1/")

344

}

345

346

headers {

347

append("User-Agent", "MyApp/1.0")

348

append("Accept", "application/json")

349

}

350

}

351

}

352

353

// All requests will use the default configuration

354

val response = client.get("users/123") // Requests https://api.example.com/v1/users/123

355

```

356

357

### DataConversion Plugin

358

359

Data conversion utilities for request/response parameters.

360

361

```kotlin { .api }

362

/**

363

* Plugin for data conversion utilities

364

*/

365

object DataConversion : HttpClientPlugin<DataConversion.Configuration, DataConversion>

366

```

367

368

## Timeout Management

369

370

### HttpTimeout Plugin

371

372

Configurable timeouts for HTTP requests.

373

374

```kotlin { .api }

375

/**

376

* Plugin for configuring HTTP request timeouts

377

*/

378

object HttpTimeout : HttpClientPlugin<HttpTimeoutCapabilityConfiguration, Unit>

379

380

/**

381

* Timeout configuration

382

*/

383

class HttpTimeoutCapabilityConfiguration {

384

/** Request timeout in milliseconds */

385

var requestTimeoutMillis: Long? = null

386

387

/** Connection timeout in milliseconds */

388

var connectTimeoutMillis: Long? = null

389

390

/** Socket timeout in milliseconds */

391

var socketTimeoutMillis: Long? = null

392

}

393

394

/**

395

* Request timeout exception

396

*/

397

class HttpRequestTimeoutException(

398

val url: String,

399

val timeoutMillis: Long

400

) : IOException("Request timeout has expired [url=$url, timeout_ms=$timeoutMillis]")

401

```

402

403

**Usage Examples:**

404

405

```kotlin

406

import io.ktor.client.*

407

import io.ktor.client.plugins.timeout.*

408

409

// Global timeout configuration

410

val timeoutClient = HttpClient {

411

install(HttpTimeout) {

412

requestTimeoutMillis = 30000 // 30 seconds

413

connectTimeoutMillis = 10000 // 10 seconds

414

socketTimeoutMillis = 20000 // 20 seconds

415

}

416

}

417

418

// Per-request timeout

419

val response = timeoutClient.get ("https://slow-api.example.com") {

420

timeout {

421

requestTimeoutMillis = 60000 // 1 minute for this request

422

}

423

}

424

```

425

426

## Caching

427

428

### HttpCache Plugin

429

430

HTTP response caching with cache control support.

431

432

```kotlin { .api }

433

/**

434

* Plugin for HTTP response caching

435

*/

436

object HttpCache : HttpClientPlugin<Unit, Unit>

437

```

438

439

## WebSocket Support

440

441

### WebSockets Plugin

442

443

WebSocket connection support for real-time communication.

444

445

```kotlin { .api }

446

/**

447

* Plugin for WebSocket support

448

*/

449

object WebSockets : HttpClientPlugin<WebSocketConfig, Unit>

450

451

/**

452

* WebSocket configuration

453

*/

454

class WebSocketConfig {

455

/** Maximum frame size in bytes */

456

var maxFrameSize: Long = Long.MAX_VALUE

457

458

/** Masking for outgoing frames */

459

var masking: Boolean = true

460

461

/** Extensions for WebSocket protocol */

462

val extensions: MutableList<WebSocketExtension<*>> = mutableListOf()

463

}

464

465

/**

466

* WebSocket session interface

467

*/

468

interface ClientWebSocketSession : WebSocketSession {

469

/** Send text frame */

470

suspend fun send(data: String)

471

472

/** Send binary frame */

473

suspend fun send(data: ByteArray)

474

475

/** Receive incoming frames */

476

val incoming: ReceiveChannel<Frame>

477

478

/** Outgoing frames channel */

479

val outgoing: SendChannel<Frame>

480

481

/** Close WebSocket connection */

482

suspend fun close(reason: CloseReason = CloseReason(CloseReason.Codes.NORMAL, ""))

483

}

484

485

/** WebSocket connection function */

486

suspend fun HttpClient.webSocket(

487

host: String = "localhost",

488

port: Int = DEFAULT_PORT,

489

path: String = "/",

490

block: suspend ClientWebSocketSession.() -> Unit

491

)

492

493

suspend fun HttpClient.ws(

494

urlString: String,

495

block: suspend ClientWebSocketSession.() -> Unit

496

)

497

```

498

499

**Usage Examples:**

500

501

```kotlin

502

import io.ktor.client.*

503

import io.ktor.client.plugins.websocket.*

504

import io.ktor.websocket.*

505

506

// Install WebSocket plugin

507

val wsClient = HttpClient {

508

install(WebSockets) {

509

maxFrameSize = 1024 * 1024 // 1MB frames

510

masking = true

511

}

512

}

513

514

// WebSocket connection

515

wsClient.webSocket("ws://localhost:8080/websocket") {

516

// Send message

517

send("Hello WebSocket!")

518

519

// Receive messages

520

for (frame in incoming) {

521

when (frame) {

522

is Frame.Text -> {

523

val message = frame.readText()

524

println("Received: $message")

525

}

526

is Frame.Binary -> {

527

val data = frame.readBytes()

528

println("Received binary: ${data.size} bytes")

529

}

530

is Frame.Close -> {

531

println("WebSocket closed: ${frame.readReason()}")

532

break

533

}

534

}

535

}

536

}

537

538

// WebSocket with URL string

539

wsClient.ws("wss://echo.websocket.org") {

540

send("Echo test message")

541

542

val response = incoming.receive()

543

if (response is Frame.Text) {

544

println("Echo response: ${response.readText()}")

545

}

546

}

547

```

548

549

## Server-Sent Events

550

551

### SSE Plugin

552

553

Server-Sent Events support for streaming data.

554

555

```kotlin { .api }

556

/**

557

* Plugin for Server-Sent Events (SSE) support

558

*/

559

object SSE : HttpClientPlugin<Unit, Unit>

560

561

/**

562

* Server-Sent Event representation

563

*/

564

data class ServerSentEvent(

565

val data: String? = null,

566

val event: String? = null,

567

val id: String? = null,

568

val retry: Long? = null,

569

val comments: String? = null

570

)

571

572

/** SSE connection function */

573

suspend fun HttpClient.sse(

574

host: String = "localhost",

575

port: Int = DEFAULT_PORT,

576

path: String = "/",

577

block: suspend SSESession.() -> Unit

578

)

579

580

/**

581

* SSE session interface

582

*/

583

interface SSESession {

584

/** Incoming server-sent events */

585

val incoming: ReceiveChannel<ServerSentEvent>

586

}

587

```

588

589

**Usage Examples:**

590

591

```kotlin

592

import io.ktor.client.*

593

import io.ktor.client.plugins.sse.*

594

595

// Install SSE plugin

596

val sseClient = HttpClient {

597

install(SSE)

598

}

599

600

// SSE connection

601

sseClient.sse("localhost", 8080, "/events") {

602

for (event in incoming) {

603

when (event.event) {

604

"message" -> println("Message: ${event.data}")

605

"update" -> println("Update: ${event.data}")

606

"error" -> println("Error: ${event.data}")

607

else -> println("Event: ${event.event}, Data: ${event.data}")

608

}

609

}

610

}

611

```

612

613

## Logging

614

615

### Logging Plugin

616

617

Comprehensive request/response logging with configurable levels.

618

619

```kotlin { .api }

620

/**

621

* Plugin for HTTP request/response logging

622

*/

623

object Logging : HttpClientPlugin<LoggingConfig, Unit>

624

625

/**

626

* Logging configuration

627

*/

628

class LoggingConfig {

629

/** Logger implementation */

630

var logger: Logger = Logger.DEFAULT

631

632

/** Logging level */

633

var level: LogLevel = LogLevel.HEADERS

634

635

/** Log request body */

636

var logRequestBody: Boolean = false

637

638

/** Log response body */

639

var logResponseBody: Boolean = false

640

641

/** Sanitize sensitive headers */

642

var sanitizeHeader: (String) -> String = { it }

643

}

644

645

/**

646

* Logging levels

647

*/

648

enum class LogLevel {

649

ALL, HEADERS, BODY, INFO, NONE

650

}

651

652

/**

653

* Logger interface

654

*/

655

interface Logger {

656

fun log(message: String)

657

658

companion object {

659

val DEFAULT: Logger = object : Logger {

660

override fun log(message: String) {

661

println(message)

662

}

663

}

664

val SIMPLE: Logger = DEFAULT

665

val EMPTY: Logger = object : Logger {

666

override fun log(message: String) {}

667

}

668

}

669

}

670

```

671

672

**Usage Examples:**

673

674

```kotlin

675

import io.ktor.client.*

676

import io.ktor.client.plugins.logging.*

677

678

// Basic logging

679

val loggingClient = HttpClient {

680

install(Logging) {

681

logger = Logger.DEFAULT

682

level = LogLevel.HEADERS

683

}

684

}

685

686

// Detailed logging

687

val detailedClient = HttpClient {

688

install(Logging) {

689

logger = Logger.DEFAULT

690

level = LogLevel.ALL

691

logRequestBody = true

692

logResponseBody = true

693

694

sanitizeHeader { header ->

695

when {

696

header.lowercase().contains("authorization") -> "***"

697

header.lowercase().contains("cookie") -> "***"

698

else -> header

699

}

700

}

701

}

702

}

703

704

// Custom logger

705

val customLogger = object : Logger {

706

override fun log(message: String) {

707

// Custom logging implementation

708

writeToLogFile(message)

709

}

710

}

711

712

val customLoggingClient = HttpClient {

713

install(Logging) {

714

logger = customLogger

715

level = LogLevel.INFO

716

}

717

}

718

```

719

720

## Types

721

722

### Plugin Configuration Types

723

724

```kotlin { .api }

725

data class PluginInstallationConfig<TConfig : Any>(

726

val plugin: HttpClientPlugin<TConfig, *>,

727

val config: TConfig

728

)

729

730

interface AuthProvider {

731

val sendWithoutRequest: Boolean

732

suspend fun addRequestHeaders(request: HttpRequestBuilder)

733

suspend fun refreshToken(response: HttpResponse): Boolean

734

}

735

736

data class CloseReason(val code: Short, val message: String) {

737

companion object Codes {

738

const val NORMAL: Short = 1000

739

const val GOING_AWAY: Short = 1001

740

const val PROTOCOL_ERROR: Short = 1002

741

const val UNSUPPORTED_DATA: Short = 1003

742

const val NO_STATUS: Short = 1005

743

const val ABNORMAL_CLOSURE: Short = 1006

744

const val INVALID_DATA: Short = 1007

745

const val POLICY_VIOLATION: Short = 1008

746

const val TOO_BIG: Short = 1009

747

const val MANDATORY_EXTENSION: Short = 1010

748

const val INTERNAL_ERROR: Short = 1011

749

const val SERVICE_RESTART: Short = 1012

750

const val TRY_AGAIN_LATER: Short = 1013

751

const val TLS_HANDSHAKE_FAILED: Short = 1015

752

}

753

}

754

```