CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-ktor--ktor-client-core-tvosarm64

Ktor HTTP Client Core for tvOS ARM64 - multiplatform asynchronous HTTP client library with coroutines support

Pending
Overview
Eval results
Files

builtin-plugins.mddocs/

Built-in Plugins

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.

Core Built-in Plugins

HttpRedirect

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

object HttpRedirect : HttpClientPlugin<HttpRedirect.Config, HttpRedirect> {
    class Config {
        var checkHttpMethod: Boolean = true
        var allowHttpsDowngrade: Boolean = false
        var maxJumps: Int = 20
        
        fun checkHttpMethod(block: (HttpMethod) -> Boolean)
        fun allowHttpsDowngrade(allow: Boolean)
    }
}

Usage Example:

val client = HttpClient {
    install(HttpRedirect) {
        checkHttpMethod = true
        allowHttpsDowngrade = false
        maxJumps = 10
    }
}

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

HttpRequestRetry

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

object HttpRequestRetry : HttpClientPlugin<HttpRequestRetry.Config, HttpRequestRetry> {
    class Config {
        var maxRetries: Int = 3
        var retryOnExceptionOrServerErrors: Boolean = true
        var delayMillis: (retry: Int) -> Long = { retry -> retry * 1000L }
        var modifyRequest: suspend HttpRequestBuilder.(retry: Int) -> Unit = {}
        
        fun retryOnException(retries: Int = 3, block: suspend RetryEventData.() -> Boolean = { true })
        fun retryOnServerErrors(maxRetries: Int = 3)
        fun retryIf(block: suspend RetryEventData.(HttpResponse) -> Boolean)
        fun exponentialDelay(base: Double = 2.0, maxDelayMs: Long = 60000)
        fun constantDelay(delayMs: Long = 1000)
        fun linearDelay(delayMs: Long = 1000)
    }
    
    class RetryEventData(
        val executionCount: Int,
        val request: HttpRequestBuilder,
        val response: HttpResponse?,
        val cause: Throwable?
    )
}

Usage Example:

val client = HttpClient {
    install(HttpRequestRetry) {
        retryOnServerErrors(maxRetries = 3)
        exponentialDelay()
        
        retryIf { request, response ->
            response.status.value >= 500
        }
        
        modifyRequest { retry ->
            header("X-Retry-Count", retry.toString())
        }
    }
}

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

HttpTimeout

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

object HttpTimeout : HttpClientPlugin<HttpTimeout.Config, HttpTimeout> {
    class Config {
        var requestTimeoutMillis: Long? = null
        var connectTimeoutMillis: Long? = null
        var socketTimeoutMillis: Long? = null
    }
}

Usage Example:

val client = HttpClient {
    install(HttpTimeout) {
        requestTimeoutMillis = 30000
        connectTimeoutMillis = 5000
        socketTimeoutMillis = 10000
    }
}

// Per-request timeout override
val response = client.get("https://slow-api.example.com/data") {
    timeout {
        requestTimeoutMillis = 60000
    }
}

UserAgent

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

object UserAgent : HttpClientPlugin<UserAgent.Config, UserAgent> {
    class Config {
        var agent: String = "Ktor HTTP Client"
    }
}

Usage Example:

val client = HttpClient {
    install(UserAgent) {
        agent = "MyApp/1.0 (https://example.com)"
    }
}

// All requests will include the User-Agent header
val response = client.get("https://httpbin.org/user-agent")

DefaultRequest

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

object DefaultRequest : HttpClientPlugin<DefaultRequest.Config, DefaultRequest> {
    class Config : HttpRequestBuilder() {
        // Inherits all HttpRequestBuilder functionality
        // for setting default URL, headers, etc.
    }
}

Usage Example:

val client = HttpClient {
    install(DefaultRequest) {
        url {
            protocol = URLProtocol.HTTPS
            host = "api.example.com"
            port = 443
        }
        header("Authorization", "Bearer $token")
        header("Content-Type", "application/json")
        parameter("api_version", "v1")
    }
}

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

HttpCallValidator

Response validation plugin for validating responses and handling exceptions.

object HttpCallValidator : HttpClientPlugin<HttpCallValidator.Config, HttpCallValidator> {
    class Config {
        internal val responseValidators = mutableListOf<suspend (response: HttpResponse) -> Unit>()
        internal val responseExceptionHandlers = mutableListOf<suspend (exception: Throwable) -> Unit>()
        
        fun validateResponse(block: suspend (response: HttpResponse) -> Unit)
        fun handleResponseException(block: suspend (exception: Throwable) -> Unit)
        fun handleResponseExceptionWithRequest(
            block: suspend (exception: Throwable, request: HttpRequest) -> Unit
        )
    }
}

Usage Example:

val client = HttpClient {
    install(HttpCallValidator) {
        validateResponse { response ->
            val statusCode = response.status.value
            if (statusCode >= 400) {
                throw ClientRequestException(response, "Request failed with status $statusCode")
            }
        }
        
        handleResponseException { exception ->
            when (exception) {
                is ClientRequestException -> {
                    println("Client error: ${exception.response.status}")
                    throw exception
                }
                is ServerResponseException -> {
                    println("Server error: ${exception.response.status}")
                    throw exception
                }
            }
        }
    }
}

HttpPlainText

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

object HttpPlainText : HttpClientPlugin<HttpPlainText.Config, HttpPlainText> {
    class Config {
        var charsets: MutableSet<Charset> = mutableSetOf(Charsets.UTF_8)
        
        fun register(
            contentType: ContentType,
            converter: suspend (text: String) -> Any
        )
        
        fun register(
            contentType: ContentType,
            converter: suspend (charset: Charset, text: String) -> Any
        )
    }
}

Usage Example:

val client = HttpClient {
    install(HttpPlainText) {
        charsets = mutableSetOf(Charsets.UTF_8, Charsets.ISO_8859_1)
        
        // Custom text converter for CSV
        register(ContentType.Text.CSV) { text ->
            text.lines().map { line -> line.split(",") }
        }
    }
}

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

HttpSend

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

object HttpSend : HttpClientPlugin<HttpSend.Config, HttpSend> {
    class Config {
        internal val interceptors = mutableListOf<suspend Sender.(HttpRequestBuilder) -> HttpResponse>()
        
        fun intercept(block: suspend Sender.(request: HttpRequestBuilder) -> HttpResponse)
    }
    
    interface Sender {
        suspend fun execute(requestBuilder: HttpRequestBuilder): HttpResponse
    }
}

Usage Example:

val client = HttpClient {
    install(HttpSend) {
        intercept { request ->
            // Log request details
            println("Sending ${request.method.value} request to ${request.url}")
            
            // Add timestamp header
            request.header("X-Request-Time", Clock.System.now().toString())
            
            // Continue with the request
            execute(request)
        }
    }
}

DataConversion

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

object DataConversion : HttpClientPlugin<DataConversion.Config, DataConversion> {
    class Config {
        internal val converters = mutableListOf<ContentConverter>()
        
        fun register(
            contentType: ContentType,
            converter: ContentConverter,
            configuration: ContentConverterConfiguration.() -> Unit = {}
        )
    }
    
    interface ContentConverter {
        suspend fun serialize(
            contentType: ContentType,
            charset: Charset,
            typeInfo: TypeInfo,
            value: Any
        ): OutgoingContent
        
        suspend fun deserialize(
            charset: Charset,
            typeInfo: TypeInfo,
            content: ByteReadChannel
        ): Any
    }
}

Usage Example:

// Note: DataConversion is typically used by higher-level serialization plugins
// like JSON, XML, etc. Direct usage is for custom serialization formats.

val client = HttpClient {
    install(DataConversion) {
        register(
            ContentType.Application.Json,
            MyJsonConverter()
        )
    }
}

BodyProgress

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

object BodyProgress : HttpClientPlugin<BodyProgress.Config, BodyProgress> {
    class Config {
        internal val sendProgressListeners = mutableListOf<ProgressListener>()
        internal val receiveProgressListeners = mutableListOf<ProgressListener>()
        
        fun onUpload(listener: ProgressListener)
        fun onDownload(listener: ProgressListener)
    }
    
    typealias ProgressListener = (bytesSentTotal: Long, contentLength: Long?) -> Unit
}

Usage Example:

val client = HttpClient {
    install(BodyProgress) {
        onUpload { bytesSentTotal, contentLength ->
            val progress = contentLength?.let { (bytesSentTotal * 100 / it).toInt() } ?: 0
            println("Upload progress: $progress% ($bytesSentTotal bytes)")
        }
        
        onDownload { bytesReceivedTotal, contentLength ->
            val progress = contentLength?.let { (bytesReceivedTotal * 100 / it).toInt() } ?: 0
            println("Download progress: $progress% ($bytesReceivedTotal bytes)")
        }
    }
}

// Progress will be tracked for file uploads/downloads
val response = client.post("https://httpbin.org/post") {
    setBody("Large file content...")
}

Installation and Configuration

All built-in plugins follow the same installation pattern:

val client = HttpClient {
    install(PluginName) {
        // Plugin-specific configuration
    }
}

Multiple plugins can be installed together:

val client = HttpClient {
    install(HttpTimeout) {
        requestTimeoutMillis = 30000
    }
    
    install(HttpRequestRetry) {
        retryOnServerErrors(maxRetries = 3)
    }
    
    install(UserAgent) {
        agent = "MyApp/1.0"
    }
    
    install(HttpCallValidator) {
        validateResponse { response ->
            if (response.status.value >= 400) {
                throw Exception("Request failed")
            }
        }
    }
}

Plugin Dependencies

Some plugins work better together or have implicit dependencies:

  • HttpCallValidator should be installed after content plugins like JSON serialization
  • HttpRequestRetry works with HttpTimeout for comprehensive error handling
  • DefaultRequest should be installed early to provide base configuration for other plugins
  • BodyProgress works with any plugin that processes request/response bodies

Best Practices

  1. Install plugins in logical order: Configuration plugins first, then processing plugins, then validation plugins
  2. Use appropriate timeouts: Configure realistic timeout values based on your use case
  3. Handle retries carefully: Avoid retrying non-idempotent operations unless specifically designed for it
  4. Validate responses: Always use HttpCallValidator for production applications
  5. Monitor progress: Use BodyProgress for large file transfers to provide user feedback
  6. Set user agents: Always identify your application with a proper User-Agent header

Install with Tessl CLI

npx tessl i tessl/maven-io-ktor--ktor-client-core-tvosarm64

docs

builtin-plugins.md

caching.md

cookies.md

engine-configuration.md

forms.md

http-client.md

index.md

plugin-system.md

request-building.md

response-handling.md

response-observation.md

utilities.md

websockets.md

tile.json