HTTP client content encoding plugin for compression and decompression in Ktor applications.
npx @tessl/cli install tessl/maven-io-ktor--ktor-client-encoding@3.2.0HTTP content compression and decompression plugin for Ktor client applications supporting gzip, deflate, and identity encodings with automatic header management and transparent content processing.
io.ktor:ktor-client-encoding:3.2.0dependencies {
implementation("io.ktor:ktor-client-encoding:3.2.0")
}import io.ktor.client.*
import io.ktor.client.plugins.compression.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.content.*
import io.ktor.util.*import io.ktor.client.*
import io.ktor.client.plugins.compression.*
val client = HttpClient {
install(ContentEncoding) {
gzip()
deflate()
identity()
}
}
// Automatic response decompression
val response = client.get("https://api.example.com/data")
val data = response.body<String>() // Automatically decompressed if needed
// Manual request compression
client.post("https://api.example.com/upload") {
compress("gzip")
setBody(largePayload)
}The content encoding system consists of four main components:
val ContentEncoding: ClientPlugin<ContentEncodingConfig>
fun HttpClientConfig<*>.ContentEncoding(
mode: ContentEncodingConfig.Mode = ContentEncodingConfig.Mode.DecompressResponse,
block: ContentEncodingConfig.() -> Unit = {
gzip()
deflate()
identity()
}
): Unitclass ContentEncodingConfig {
enum class Mode(internal val request: Boolean, internal val response: Boolean) {
CompressRequest(true, false),
DecompressResponse(false, true),
All(true, true)
}
var mode: Mode
fun gzip(quality: Float? = null): Unit
fun deflate(quality: Float? = null): Unit
fun identity(quality: Float? = null): Unit
fun customEncoder(encoder: ContentEncoder, quality: Float? = null): Unit
}Install and configure the ContentEncoding plugin with compression algorithms, quality values, and operation modes.
import io.ktor.client.*
import io.ktor.client.plugins.compression.*
val client = HttpClient {
install(ContentEncoding) {
mode = ContentEncodingConfig.Mode.All
gzip(0.9f) // High priority
deflate(0.8f) // Medium priority
identity(0.1f) // Low priority fallback
}
}Key API:
ContentEncoding plugin object for installationContentEncodingConfig.Mode enum for operation controlSee Configuration for detailed configuration options.
Control whether the plugin compresses outgoing requests, decompresses incoming responses, or handles both operations.
enum class ContentEncodingConfig.Mode(internal val request: Boolean, internal val response: Boolean) {
CompressRequest(true, false),
DecompressResponse(false, true),
All(true, true),
}Usage:
// Only decompress responses (default)
install(ContentEncoding) {
mode = ContentEncodingConfig.Mode.DecompressResponse
}
// Only compress requests
install(ContentEncoding) {
mode = ContentEncodingConfig.Mode.CompressRequest
}
// Both compress requests and decompress responses
install(ContentEncoding) {
mode = ContentEncodingConfig.Mode.All
}See Configuration for mode-specific behaviors and use cases.
Pre-built content encoders for standard HTTP compression algorithms with platform-specific implementations.
object GZipEncoder : ContentEncoder {
override val name: String // "gzip"
}
object DeflateEncoder : ContentEncoder {
override val name: String // "deflate"
}
object IdentityEncoder : ContentEncoder {
override val name: String // "identity"
}Usage:
install(ContentEncoding) {
gzip() // Enable gzip compression
deflate() // Enable deflate compression
identity() // Enable identity (no-op) encoding
}See Encoders for encoder details and custom encoder implementation.
Compress outgoing request bodies using specified encoding algorithms for individual requests or globally.
fun HttpRequestBuilder.compress(vararg contentEncoderName: String): Unit
fun HttpRequestBuilder.compress(contentEncoderNames: List<String>): UnitUsage:
// Per-request compression
client.post("/api/upload") {
compress("gzip", "deflate")
setBody(largeData)
}
// List-based compression
client.put("/api/update") {
compress(listOf("gzip"))
setBody(payload)
}Key Features:
See Request Compression for advanced compression scenarios and configuration.
Automatically decompress incoming response bodies based on Content-Encoding headers with transparent processing.
val HttpResponse.appliedDecoders: List<String>Usage:
val response = client.get("https://api.example.com/compressed-data")
// Access decompressed content directly
val content = response.body<String>()
// Check which decoders were applied
val usedEncodings = response.appliedDecoders
println("Applied decoders: $usedEncodings") // e.g., ["gzip", "deflate"]Key Features:
See Response Decompression for decompression behavior and troubleshooting.
Utilities for compressing OutgoingContent using ContentEncoder implementations.
fun OutgoingContent.compressed(
contentEncoder: ContentEncoder,
coroutineContext: CoroutineContext = EmptyCoroutineContext
): OutgoingContent?Usage:
import io.ktor.http.content.*
import io.ktor.util.*
// Manually compress content before sending
val originalContent: OutgoingContent = TextContent("Large text payload", ContentType.Text.Plain)
val compressedContent = originalContent.compressed(GZipEncoder)Key Features:
interface ContentEncoder : Encoder {
/**
* Encoder identifier to use in http headers.
*/
val name: String
/**
* Provides an estimation for the compressed length based on the originalLength or return null if it's impossible.
*/
fun predictCompressedLength(contentLength: Long): Long? = null
}
interface Encoder {
/**
* Launch coroutine to encode source bytes.
*/
fun encode(
source: ByteReadChannel,
coroutineContext: CoroutineContext = EmptyCoroutineContext
): ByteReadChannel
/**
* Launch coroutine to encode source bytes.
*/
fun encode(
source: ByteWriteChannel,
coroutineContext: CoroutineContext = EmptyCoroutineContext
): ByteWriteChannel
/**
* Launch coroutine to decode source bytes.
*/
fun decode(
source: ByteReadChannel,
coroutineContext: CoroutineContext = EmptyCoroutineContext
): ByteReadChannel
}class UnsupportedContentEncodingException(encoding: String) : IllegalStateException("Content-Encoding: $encoding unsupported.")Error Scenarios:
try {
val response = client.get("https://api.example.com/data")
val content = response.body<String>()
} catch (e: UnsupportedContentEncodingException) {
println("Unsupported encoding: ${e.message}")
// Handle unsupported encoding
}Internal attribute keys used by the plugin for tracking compression state.
val CompressionListAttribute: AttributeKey<List<String>>
val DecompressionListAttribute: AttributeKey<List<String>>Usage:
// These attributes are used internally by the plugin
// CompressionListAttribute - tracks requested compression encoders
// DecompressionListAttribute - tracks applied decompression encoders
// Access applied decoders through the convenience property
val appliedDecoders = response.appliedDecoders // Uses DecompressionListAttribute internallyimport io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.compression.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
suspend fun main() {
val client = HttpClient(CIO) {
install(ContentEncoding) {
mode = ContentEncodingConfig.Mode.All
gzip(0.9f)
deflate(0.8f)
identity()
}
}
// Upload with compression
val uploadResponse = client.post("https://api.example.com/upload") {
compress("gzip")
setBody("Large payload data...")
}
// Download with automatic decompression
val downloadResponse = client.get("https://api.example.com/download")
val content = downloadResponse.body<String>()
// Check applied decoders
val decoders = downloadResponse.appliedDecoders
println("Response decompressed with: $decoders")
client.close()
}