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
```