CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-ktor--ktor-server-compression-jvm

A Ktor server plugin that provides HTTP response compression and request decompression capabilities with support for gzip, deflate, and identity encoding algorithms.

Pending
Overview
Eval results
Files

decompression.mddocs/

Request Decompression

The Compression plugin automatically decompresses incoming request bodies that have been compressed with supported algorithms. It handles Content-Encoding headers and tracks which decoders were applied.

Decompression Process

When the plugin receives a request with a Content-Encoding header:

  1. Parses the encoding value(s) from the header
  2. Matches available decoders with the specified encodings
  3. Applies decoders in reverse order (last encoding applied is first to be removed)
  4. Updates or removes the Content-Encoding header
  5. Tracks applied decoders for inspection

Decoder Tracking

val ApplicationRequest.appliedDecoders: List<String>

Access the list of decoder names that were used to decompress the request body:

routing {
    post("/upload") {
        val decoders = call.request.appliedDecoders
        if (decoders.isNotEmpty()) {
            println("Request was decompressed using: ${decoders.joinToString(", ")}")
        }
        
        val body = call.receiveText()
        // Process decompressed body...
        call.respond("Received")
    }
}

Supported Decompression Algorithms

The plugin uses the same ContentEncoder implementations for both compression and decompression:

  • gzip - Handles gzip-compressed request bodies
  • deflate - Handles deflate-compressed request bodies
  • identity - Pass-through for uncompressed content

Header Management

Complete Decompression

When all encodings can be decompressed, the plugin:

  • Removes the Content-Encoding header entirely
  • May remove or adjust the Content-Length header
  • Adds Transfer-Encoding: chunked if needed
Request headers before decompression:
Content-Encoding: gzip
Content-Length: 1024

Request headers after decompression:  
Transfer-Encoding: chunked
(Content-Encoding and Content-Length removed)

Partial Decompression

When only some encodings can be decompressed, the plugin:

  • Updates the Content-Encoding header with remaining encodings
  • Tracks which decoders were successfully applied
Request headers before decompression:
Content-Encoding: gzip, custom-encoding

Request headers after decompression:
Content-Encoding: custom-encoding
(gzip removed, custom-encoding remains)

Decompression Control

Operation Mode

Control decompression behavior via the plugin's operation mode:

install(Compression) {
    mode = CompressionConfig.Mode.DecompressRequest  // Only decompress requests
    mode = CompressionConfig.Mode.CompressResponse   // No decompression
    mode = CompressionConfig.Mode.All               // Both compress and decompress (default)
}

Suppression

Disable decompression for specific requests:

fun ApplicationCall.suppressDecompression()
val ApplicationCall.isDecompressionSuppressed: Boolean
routing {
    post("/raw-upload") {
        // Keep request body compressed
        call.suppressDecompression()
        
        // Receive raw compressed bytes
        val compressedBody = call.receive<ByteArray>()
        // Handle compressed data directly...
    }
    
    post("/check-suppressed") {
        if (call.isDecompressionSuppressed) {
            // Handle suppressed case
        } else {
            // Normal decompression will occur
            val decompressedText = call.receiveText()
        }
    }
}

Error Handling

The plugin handles various decompression scenarios gracefully:

Missing Content-Encoding

Requests without Content-Encoding headers are processed normally without decompression attempts.

Unsupported Encodings

When encountering unknown encodings:

  • Supported encodings are still processed
  • Unsupported encodings remain in the Content-Encoding header
  • The request continues processing with partial decompression

Malformed Compressed Data

Decompression errors are propagated as exceptions that can be handled by error handling mechanisms.

Usage Examples

Basic Decompression

install(Compression)  // Enables decompression by default

routing {
    post("/api/data") {
        // Automatically decompressed if client sent compressed request
        val data = call.receive<MyDataClass>()
        call.respond("Processed ${data}")
    }
}

Conditional Processing

routing {
    post("/upload") {
        val wasCompressed = call.request.appliedDecoders.isNotEmpty()
        val contentLength = call.request.headers[HttpHeaders.ContentLength]?.toLongOrNull()
        
        when {
            wasCompressed -> {
                logger.info("Received compressed upload (${call.request.appliedDecoders})")
            }
            contentLength != null && contentLength > 1024 * 1024 -> {
                logger.warn("Large uncompressed upload: $contentLength bytes")
            }
        }
        
        val content = call.receiveText()
        // Process content...
    }
}

Custom Decoder Integration

install(Compression) {
    // Add custom decoder alongside built-in ones
    encoder(MyCustomEncoder) {
        // Custom encoder handles both compression and decompression
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-io-ktor--ktor-server-compression-jvm

docs

conditions.md

configuration.md

control.md

decompression.md

encoding.md

index.md

tile.json