0
# Request Decompression
1
2
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.
3
4
## Decompression Process
5
6
When the plugin receives a request with a `Content-Encoding` header:
7
8
1. Parses the encoding value(s) from the header
9
2. Matches available decoders with the specified encodings
10
3. Applies decoders in reverse order (last encoding applied is first to be removed)
11
4. Updates or removes the `Content-Encoding` header
12
5. Tracks applied decoders for inspection
13
14
## Decoder Tracking
15
16
```kotlin { .api }
17
val ApplicationRequest.appliedDecoders: List<String>
18
```
19
20
Access the list of decoder names that were used to decompress the request body:
21
22
```kotlin
23
routing {
24
post("/upload") {
25
val decoders = call.request.appliedDecoders
26
if (decoders.isNotEmpty()) {
27
println("Request was decompressed using: ${decoders.joinToString(", ")}")
28
}
29
30
val body = call.receiveText()
31
// Process decompressed body...
32
call.respond("Received")
33
}
34
}
35
```
36
37
## Supported Decompression Algorithms
38
39
The plugin uses the same `ContentEncoder` implementations for both compression and decompression:
40
41
- **gzip** - Handles gzip-compressed request bodies
42
- **deflate** - Handles deflate-compressed request bodies
43
- **identity** - Pass-through for uncompressed content
44
45
## Header Management
46
47
### Complete Decompression
48
49
When all encodings can be decompressed, the plugin:
50
- Removes the `Content-Encoding` header entirely
51
- May remove or adjust the `Content-Length` header
52
- Adds `Transfer-Encoding: chunked` if needed
53
54
```
55
Request headers before decompression:
56
Content-Encoding: gzip
57
Content-Length: 1024
58
59
Request headers after decompression:
60
Transfer-Encoding: chunked
61
(Content-Encoding and Content-Length removed)
62
```
63
64
### Partial Decompression
65
66
When only some encodings can be decompressed, the plugin:
67
- Updates the `Content-Encoding` header with remaining encodings
68
- Tracks which decoders were successfully applied
69
70
```
71
Request headers before decompression:
72
Content-Encoding: gzip, custom-encoding
73
74
Request headers after decompression:
75
Content-Encoding: custom-encoding
76
(gzip removed, custom-encoding remains)
77
```
78
79
## Decompression Control
80
81
### Operation Mode
82
83
Control decompression behavior via the plugin's operation mode:
84
85
```kotlin
86
install(Compression) {
87
mode = CompressionConfig.Mode.DecompressRequest // Only decompress requests
88
mode = CompressionConfig.Mode.CompressResponse // No decompression
89
mode = CompressionConfig.Mode.All // Both compress and decompress (default)
90
}
91
```
92
93
### Suppression
94
95
Disable decompression for specific requests:
96
97
```kotlin { .api }
98
fun ApplicationCall.suppressDecompression()
99
val ApplicationCall.isDecompressionSuppressed: Boolean
100
```
101
102
```kotlin
103
routing {
104
post("/raw-upload") {
105
// Keep request body compressed
106
call.suppressDecompression()
107
108
// Receive raw compressed bytes
109
val compressedBody = call.receive<ByteArray>()
110
// Handle compressed data directly...
111
}
112
113
post("/check-suppressed") {
114
if (call.isDecompressionSuppressed) {
115
// Handle suppressed case
116
} else {
117
// Normal decompression will occur
118
val decompressedText = call.receiveText()
119
}
120
}
121
}
122
```
123
124
## Error Handling
125
126
The plugin handles various decompression scenarios gracefully:
127
128
### Missing Content-Encoding
129
Requests without `Content-Encoding` headers are processed normally without decompression attempts.
130
131
### Unsupported Encodings
132
When encountering unknown encodings:
133
- Supported encodings are still processed
134
- Unsupported encodings remain in the `Content-Encoding` header
135
- The request continues processing with partial decompression
136
137
### Malformed Compressed Data
138
Decompression errors are propagated as exceptions that can be handled by error handling mechanisms.
139
140
## Usage Examples
141
142
### Basic Decompression
143
144
```kotlin
145
install(Compression) // Enables decompression by default
146
147
routing {
148
post("/api/data") {
149
// Automatically decompressed if client sent compressed request
150
val data = call.receive<MyDataClass>()
151
call.respond("Processed ${data}")
152
}
153
}
154
```
155
156
### Conditional Processing
157
158
```kotlin
159
routing {
160
post("/upload") {
161
val wasCompressed = call.request.appliedDecoders.isNotEmpty()
162
val contentLength = call.request.headers[HttpHeaders.ContentLength]?.toLongOrNull()
163
164
when {
165
wasCompressed -> {
166
logger.info("Received compressed upload (${call.request.appliedDecoders})")
167
}
168
contentLength != null && contentLength > 1024 * 1024 -> {
169
logger.warn("Large uncompressed upload: $contentLength bytes")
170
}
171
}
172
173
val content = call.receiveText()
174
// Process content...
175
}
176
}
177
```
178
179
### Custom Decoder Integration
180
181
```kotlin
182
install(Compression) {
183
// Add custom decoder alongside built-in ones
184
encoder(MyCustomEncoder) {
185
// Custom encoder handles both compression and decompression
186
}
187
}
188
```