or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

builtin-plugins.mdcaching.mdcookies.mdengine-configuration.mdforms.mdhttp-client.mdindex.mdplugin-system.mdrequest-building.mdresponse-handling.mdresponse-observation.mdutilities.mdwebsockets.md

builtin-plugins.mddocs/

0

# Built-in Plugins

1

2

The Ktor HTTP Client Core comes with a comprehensive set of built-in plugins that provide essential functionality for HTTP client operations. These plugins handle common cross-cutting concerns like redirects, retries, timeouts, response validation, and more.

3

4

## Core Built-in Plugins

5

6

### HttpRedirect

7

8

Automatic HTTP redirect handling plugin that follows redirect responses according to HTTP specifications.

9

10

```kotlin { .api }

11

object HttpRedirect : HttpClientPlugin<HttpRedirect.Config, HttpRedirect> {

12

class Config {

13

var checkHttpMethod: Boolean = true

14

var allowHttpsDowngrade: Boolean = false

15

var maxJumps: Int = 20

16

17

fun checkHttpMethod(block: (HttpMethod) -> Boolean)

18

fun allowHttpsDowngrade(allow: Boolean)

19

}

20

}

21

```

22

23

**Usage Example:**

24

25

```kotlin

26

val client = HttpClient {

27

install(HttpRedirect) {

28

checkHttpMethod = true

29

allowHttpsDowngrade = false

30

maxJumps = 10

31

}

32

}

33

34

// Automatically follows redirects

35

val response = client.get("https://httpbin.org/redirect/3")

36

```

37

38

### HttpRequestRetry

39

40

Request retry logic plugin that automatically retries failed requests based on configurable conditions.

41

42

```kotlin { .api }

43

object HttpRequestRetry : HttpClientPlugin<HttpRequestRetry.Config, HttpRequestRetry> {

44

class Config {

45

var maxRetries: Int = 3

46

var retryOnExceptionOrServerErrors: Boolean = true

47

var delayMillis: (retry: Int) -> Long = { retry -> retry * 1000L }

48

var modifyRequest: suspend HttpRequestBuilder.(retry: Int) -> Unit = {}

49

50

fun retryOnException(retries: Int = 3, block: suspend RetryEventData.() -> Boolean = { true })

51

fun retryOnServerErrors(maxRetries: Int = 3)

52

fun retryIf(block: suspend RetryEventData.(HttpResponse) -> Boolean)

53

fun exponentialDelay(base: Double = 2.0, maxDelayMs: Long = 60000)

54

fun constantDelay(delayMs: Long = 1000)

55

fun linearDelay(delayMs: Long = 1000)

56

}

57

58

class RetryEventData(

59

val executionCount: Int,

60

val request: HttpRequestBuilder,

61

val response: HttpResponse?,

62

val cause: Throwable?

63

)

64

}

65

```

66

67

**Usage Example:**

68

69

```kotlin

70

val client = HttpClient {

71

install(HttpRequestRetry) {

72

retryOnServerErrors(maxRetries = 3)

73

exponentialDelay()

74

75

retryIf { request, response ->

76

response.status.value >= 500

77

}

78

79

modifyRequest { retry ->

80

header("X-Retry-Count", retry.toString())

81

}

82

}

83

}

84

85

// Automatically retries on failures

86

val response = client.get("https://unstable-api.example.com/data")

87

```

88

89

### HttpTimeout

90

91

Request timeout handling plugin for configuring connection, request, and socket timeouts.

92

93

```kotlin { .api }

94

object HttpTimeout : HttpClientPlugin<HttpTimeout.Config, HttpTimeout> {

95

class Config {

96

var requestTimeoutMillis: Long? = null

97

var connectTimeoutMillis: Long? = null

98

var socketTimeoutMillis: Long? = null

99

}

100

}

101

```

102

103

**Usage Example:**

104

105

```kotlin

106

val client = HttpClient {

107

install(HttpTimeout) {

108

requestTimeoutMillis = 30000

109

connectTimeoutMillis = 5000

110

socketTimeoutMillis = 10000

111

}

112

}

113

114

// Per-request timeout override

115

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

116

timeout {

117

requestTimeoutMillis = 60000

118

}

119

}

120

```

121

122

### UserAgent

123

124

User agent header plugin for setting a consistent User-Agent header across all requests.

125

126

```kotlin { .api }

127

object UserAgent : HttpClientPlugin<UserAgent.Config, UserAgent> {

128

class Config {

129

var agent: String = "Ktor HTTP Client"

130

}

131

}

132

```

133

134

**Usage Example:**

135

136

```kotlin

137

val client = HttpClient {

138

install(UserAgent) {

139

agent = "MyApp/1.0 (https://example.com)"

140

}

141

}

142

143

// All requests will include the User-Agent header

144

val response = client.get("https://httpbin.org/user-agent")

145

```

146

147

### DefaultRequest

148

149

Default request configuration plugin for applying common settings to all requests.

150

151

```kotlin { .api }

152

object DefaultRequest : HttpClientPlugin<DefaultRequest.Config, DefaultRequest> {

153

class Config : HttpRequestBuilder() {

154

// Inherits all HttpRequestBuilder functionality

155

// for setting default URL, headers, etc.

156

}

157

}

158

```

159

160

**Usage Example:**

161

162

```kotlin

163

val client = HttpClient {

164

install(DefaultRequest) {

165

url {

166

protocol = URLProtocol.HTTPS

167

host = "api.example.com"

168

port = 443

169

}

170

header("Authorization", "Bearer $token")

171

header("Content-Type", "application/json")

172

parameter("api_version", "v1")

173

}

174

}

175

176

// All requests inherit default configuration

177

val response = client.get("/users") // Calls https://api.example.com/users?api_version=v1

178

```

179

180

### HttpCallValidator

181

182

Response validation plugin for validating responses and handling exceptions.

183

184

```kotlin { .api }

185

object HttpCallValidator : HttpClientPlugin<HttpCallValidator.Config, HttpCallValidator> {

186

class Config {

187

internal val responseValidators = mutableListOf<suspend (response: HttpResponse) -> Unit>()

188

internal val responseExceptionHandlers = mutableListOf<suspend (exception: Throwable) -> Unit>()

189

190

fun validateResponse(block: suspend (response: HttpResponse) -> Unit)

191

fun handleResponseException(block: suspend (exception: Throwable) -> Unit)

192

fun handleResponseExceptionWithRequest(

193

block: suspend (exception: Throwable, request: HttpRequest) -> Unit

194

)

195

}

196

}

197

```

198

199

**Usage Example:**

200

201

```kotlin

202

val client = HttpClient {

203

install(HttpCallValidator) {

204

validateResponse { response ->

205

val statusCode = response.status.value

206

if (statusCode >= 400) {

207

throw ClientRequestException(response, "Request failed with status $statusCode")

208

}

209

}

210

211

handleResponseException { exception ->

212

when (exception) {

213

is ClientRequestException -> {

214

println("Client error: ${exception.response.status}")

215

throw exception

216

}

217

is ServerResponseException -> {

218

println("Server error: ${exception.response.status}")

219

throw exception

220

}

221

}

222

}

223

}

224

}

225

```

226

227

### HttpPlainText

228

229

Plain text content handling plugin for automatic text serialization and deserialization.

230

231

```kotlin { .api }

232

object HttpPlainText : HttpClientPlugin<HttpPlainText.Config, HttpPlainText> {

233

class Config {

234

var charsets: MutableSet<Charset> = mutableSetOf(Charsets.UTF_8)

235

236

fun register(

237

contentType: ContentType,

238

converter: suspend (text: String) -> Any

239

)

240

241

fun register(

242

contentType: ContentType,

243

converter: suspend (charset: Charset, text: String) -> Any

244

)

245

}

246

}

247

```

248

249

**Usage Example:**

250

251

```kotlin

252

val client = HttpClient {

253

install(HttpPlainText) {

254

charsets = mutableSetOf(Charsets.UTF_8, Charsets.ISO_8859_1)

255

256

// Custom text converter for CSV

257

register(ContentType.Text.CSV) { text ->

258

text.lines().map { line -> line.split(",") }

259

}

260

}

261

}

262

263

// Automatic text conversion

264

val csvData: List<List<String>> = client.get("https://example.com/data.csv").body()

265

```

266

267

### HttpSend

268

269

Request sending pipeline plugin for intercepting and modifying the send phase of requests.

270

271

```kotlin { .api }

272

object HttpSend : HttpClientPlugin<HttpSend.Config, HttpSend> {

273

class Config {

274

internal val interceptors = mutableListOf<suspend Sender.(HttpRequestBuilder) -> HttpResponse>()

275

276

fun intercept(block: suspend Sender.(request: HttpRequestBuilder) -> HttpResponse)

277

}

278

279

interface Sender {

280

suspend fun execute(requestBuilder: HttpRequestBuilder): HttpResponse

281

}

282

}

283

```

284

285

**Usage Example:**

286

287

```kotlin

288

val client = HttpClient {

289

install(HttpSend) {

290

intercept { request ->

291

// Log request details

292

println("Sending ${request.method.value} request to ${request.url}")

293

294

// Add timestamp header

295

request.header("X-Request-Time", Clock.System.now().toString())

296

297

// Continue with the request

298

execute(request)

299

}

300

}

301

}

302

```

303

304

### DataConversion

305

306

Data conversion plugin for automatic serialization and deserialization of request/response bodies.

307

308

```kotlin { .api }

309

object DataConversion : HttpClientPlugin<DataConversion.Config, DataConversion> {

310

class Config {

311

internal val converters = mutableListOf<ContentConverter>()

312

313

fun register(

314

contentType: ContentType,

315

converter: ContentConverter,

316

configuration: ContentConverterConfiguration.() -> Unit = {}

317

)

318

}

319

320

interface ContentConverter {

321

suspend fun serialize(

322

contentType: ContentType,

323

charset: Charset,

324

typeInfo: TypeInfo,

325

value: Any

326

): OutgoingContent

327

328

suspend fun deserialize(

329

charset: Charset,

330

typeInfo: TypeInfo,

331

content: ByteReadChannel

332

): Any

333

}

334

}

335

```

336

337

**Usage Example:**

338

339

```kotlin

340

// Note: DataConversion is typically used by higher-level serialization plugins

341

// like JSON, XML, etc. Direct usage is for custom serialization formats.

342

343

val client = HttpClient {

344

install(DataConversion) {

345

register(

346

ContentType.Application.Json,

347

MyJsonConverter()

348

)

349

}

350

}

351

```

352

353

### BodyProgress

354

355

Body upload/download progress tracking plugin for monitoring transfer progress.

356

357

```kotlin { .api }

358

object BodyProgress : HttpClientPlugin<BodyProgress.Config, BodyProgress> {

359

class Config {

360

internal val sendProgressListeners = mutableListOf<ProgressListener>()

361

internal val receiveProgressListeners = mutableListOf<ProgressListener>()

362

363

fun onUpload(listener: ProgressListener)

364

fun onDownload(listener: ProgressListener)

365

}

366

367

typealias ProgressListener = (bytesSentTotal: Long, contentLength: Long?) -> Unit

368

}

369

```

370

371

**Usage Example:**

372

373

```kotlin

374

val client = HttpClient {

375

install(BodyProgress) {

376

onUpload { bytesSentTotal, contentLength ->

377

val progress = contentLength?.let { (bytesSentTotal * 100 / it).toInt() } ?: 0

378

println("Upload progress: $progress% ($bytesSentTotal bytes)")

379

}

380

381

onDownload { bytesReceivedTotal, contentLength ->

382

val progress = contentLength?.let { (bytesReceivedTotal * 100 / it).toInt() } ?: 0

383

println("Download progress: $progress% ($bytesReceivedTotal bytes)")

384

}

385

}

386

}

387

388

// Progress will be tracked for file uploads/downloads

389

val response = client.post("https://httpbin.org/post") {

390

setBody("Large file content...")

391

}

392

```

393

394

## Installation and Configuration

395

396

All built-in plugins follow the same installation pattern:

397

398

```kotlin

399

val client = HttpClient {

400

install(PluginName) {

401

// Plugin-specific configuration

402

}

403

}

404

```

405

406

Multiple plugins can be installed together:

407

408

```kotlin

409

val client = HttpClient {

410

install(HttpTimeout) {

411

requestTimeoutMillis = 30000

412

}

413

414

install(HttpRequestRetry) {

415

retryOnServerErrors(maxRetries = 3)

416

}

417

418

install(UserAgent) {

419

agent = "MyApp/1.0"

420

}

421

422

install(HttpCallValidator) {

423

validateResponse { response ->

424

if (response.status.value >= 400) {

425

throw Exception("Request failed")

426

}

427

}

428

}

429

}

430

```

431

432

## Plugin Dependencies

433

434

Some plugins work better together or have implicit dependencies:

435

436

- **HttpCallValidator** should be installed after content plugins like JSON serialization

437

- **HttpRequestRetry** works with **HttpTimeout** for comprehensive error handling

438

- **DefaultRequest** should be installed early to provide base configuration for other plugins

439

- **BodyProgress** works with any plugin that processes request/response bodies

440

441

## Best Practices

442

443

1. **Install plugins in logical order**: Configuration plugins first, then processing plugins, then validation plugins

444

2. **Use appropriate timeouts**: Configure realistic timeout values based on your use case

445

3. **Handle retries carefully**: Avoid retrying non-idempotent operations unless specifically designed for it

446

4. **Validate responses**: Always use HttpCallValidator for production applications

447

5. **Monitor progress**: Use BodyProgress for large file transfers to provide user feedback

448

6. **Set user agents**: Always identify your application with a proper User-Agent header