or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdencoders.mdindex.mdrequest-compression.mdresponse-decompression.md

request-compression.mddocs/

0

# Request Compression

1

2

Compress outgoing HTTP request bodies to reduce bandwidth usage and improve upload performance using configurable compression algorithms.

3

4

## Request Compression API

5

6

```kotlin { .api }

7

/**

8

* Compresses request body using ContentEncoding plugin.

9

* @param contentEncoderName names of compression encoders to use, such as "gzip", "deflate", etc

10

*/

11

fun HttpRequestBuilder.compress(vararg contentEncoderName: String): Unit

12

13

/**

14

* Compress request body using ContentEncoding plugin.

15

* @param contentEncoderNames names of compression encoders to use, such as "gzip", "deflate", etc

16

*/

17

fun HttpRequestBuilder.compress(contentEncoderNames: List<String>): Unit

18

```

19

20

## Basic Request Compression

21

22

### Per-Request Compression

23

24

```kotlin

25

import io.ktor.client.request.*

26

import io.ktor.client.plugins.compression.*

27

28

// Single encoder

29

client.post("/api/upload") {

30

compress("gzip")

31

setBody("Large payload data")

32

}

33

34

// Multiple encoders (applied in order)

35

client.put("/api/update") {

36

compress("gzip", "deflate")

37

setBody(largeData)

38

}

39

40

// List-based specification

41

client.patch("/api/modify") {

42

compress(listOf("deflate", "gzip"))

43

setBody(payload)

44

}

45

```

46

47

### Global Request Compression Mode

48

49

```kotlin

50

val client = HttpClient {

51

install(ContentEncoding) {

52

mode = ContentEncodingConfig.Mode.CompressRequest // Only compress requests

53

gzip()

54

deflate()

55

}

56

}

57

58

// All requests can now use compression

59

client.post("/upload1") {

60

compress("gzip")

61

setBody(data1)

62

}

63

64

client.post("/upload2") {

65

compress("deflate")

66

setBody(data2)

67

}

68

```

69

70

### Bidirectional Mode

71

72

```kotlin

73

val client = HttpClient {

74

install(ContentEncoding) {

75

mode = ContentEncodingConfig.Mode.All // Compress requests AND decompress responses

76

gzip()

77

deflate()

78

identity()

79

}

80

}

81

82

client.post("/api/data") {

83

compress("gzip")

84

setBody(requestData)

85

}

86

// Response automatically decompressed if server sends compressed data

87

```

88

89

## Compression Behavior

90

91

### Header Management

92

93

```kotlin

94

client.post("/upload") {

95

compress("gzip")

96

setBody("Data to compress")

97

}

98

99

// Automatically sets: Content-Encoding: gzip

100

// Original Content-Length header is removed (compressed length is different)

101

// Vary header includes Accept-Encoding

102

```

103

104

### Multi-Layer Compression

105

106

```kotlin

107

// Apply multiple compression layers

108

client.post("/complex-upload") {

109

compress("deflate", "gzip") // deflate first, then gzip

110

setBody(complexData)

111

}

112

113

// Server must decompress in reverse order: gzip first, then deflate

114

```

115

116

**Processing Order:**

117

1. Original content → deflate compression → intermediate result

118

2. Intermediate result → gzip compression → final compressed content

119

3. Headers: `Content-Encoding: deflate, gzip`

120

121

### Compression with Content Types

122

123

```kotlin

124

import io.ktor.http.*

125

126

// JSON data compression

127

client.post("/api/json") {

128

compress("gzip")

129

contentType(ContentType.Application.Json)

130

setBody("""{"large": "json", "data": "here"}""")

131

}

132

133

// Binary data compression

134

client.post("/api/binary") {

135

compress("deflate")

136

contentType(ContentType.Application.OctetStream)

137

setBody(binaryData)

138

}

139

140

// Form data compression

141

client.post("/api/form") {

142

compress("gzip")

143

contentType(ContentType.Application.FormUrlEncoded)

144

setBody(formParameters)

145

}

146

```

147

148

## Advanced Request Compression

149

150

### Conditional Compression

151

152

```kotlin

153

suspend fun uploadWithConditionalCompression(data: ByteArray) {

154

val shouldCompress = data.size > 1024 // Only compress large payloads

155

156

client.post("/upload") {

157

if (shouldCompress) {

158

compress("gzip")

159

}

160

setBody(data)

161

}

162

}

163

```

164

165

### Compression Strategy by Content Type

166

167

```kotlin

168

suspend fun uploadWithSmartCompression(content: Any, contentType: ContentType) {

169

client.post("/smart-upload") {

170

when (contentType) {

171

ContentType.Application.Json,

172

ContentType.Text.Plain,

173

ContentType.Application.Xml -> {

174

compress("gzip") // Text-based content compresses well

175

}

176

ContentType.Image.JPEG,

177

ContentType.Image.PNG -> {

178

// Images are already compressed, skip compression

179

}

180

else -> {

181

compress("deflate") // Default to deflate for other types

182

}

183

}

184

contentType(contentType)

185

setBody(content)

186

}

187

}

188

```

189

190

### Large File Upload with Compression

191

192

```kotlin

193

import io.ktor.client.request.forms.*

194

import io.ktor.http.content.*

195

196

suspend fun uploadLargeFile(file: ByteArray) {

197

client.post("/large-upload") {

198

compress("gzip")

199

setBody(MultiPartFormDataContent(

200

formData {

201

append("file", file, Headers.build {

202

append(HttpHeaders.ContentDisposition, "filename=large-file.dat")

203

})

204

}

205

))

206

}

207

}

208

```

209

210

## Pipeline Integration

211

212

### Request Processing Pipeline

213

214

```kotlin

215

// Compression occurs in the request pipeline after content rendering

216

// Order: Content Creation → Rendering → Compression → Network Send

217

218

client.post("/data") {

219

// 1. Content created

220

setBody(originalContent)

221

222

// 2. Content rendered to OutgoingContent

223

// 3. Compression applied (if compress() called)

224

compress("gzip")

225

226

// 4. Compressed content sent over network

227

}

228

```

229

230

### Compression Attributes

231

232

```kotlin { .api }

233

internal val CompressionListAttribute: AttributeKey<List<String>>

234

```

235

236

**Internal Usage:**

237

```kotlin

238

// The compress() function sets internal attributes

239

client.post("/upload") {

240

compress("gzip", "deflate")

241

// Internally: attributes.put(CompressionListAttribute, listOf("gzip", "deflate"))

242

setBody(data)

243

}

244

```

245

246

## Error Handling

247

248

### Unsupported Encoder Names

249

250

```kotlin

251

try {

252

client.post("/upload") {

253

compress("unknown-algorithm") // Not registered in ContentEncodingConfig

254

setBody(data)

255

}

256

} catch (e: UnsupportedContentEncodingException) {

257

println("Compression failed: ${e.message}")

258

// Fallback to uncompressed upload

259

client.post("/upload") {

260

setBody(data)

261

}

262

}

263

```

264

265

### Compression Failure Handling

266

267

```kotlin

268

suspend fun safeCompressedUpload(data: ByteArray) {

269

try {

270

// Attempt compressed upload

271

client.post("/upload") {

272

compress("gzip")

273

setBody(data)

274

}

275

} catch (e: Exception) {

276

println("Compressed upload failed: ${e.message}")

277

278

// Retry without compression

279

client.post("/upload") {

280

setBody(data)

281

}

282

}

283

}

284

```

285

286

## Performance Considerations

287

288

### Compression Threshold

289

290

```kotlin

291

suspend fun efficientUpload(data: ByteArray) {

292

val compressionThreshold = 1024 // Don't compress small payloads

293

294

client.post("/upload") {

295

if (data.size >= compressionThreshold) {

296

compress("gzip")

297

}

298

setBody(data)

299

}

300

}

301

```

302

303

### Encoder Selection for Performance

304

305

```kotlin

306

// Fast compression for real-time uploads

307

client.post("/realtime-data") {

308

compress("deflate") // Generally faster than gzip

309

setBody(realtimeData)

310

}

311

312

// Best compression for large uploads

313

client.post("/large-file") {

314

compress("gzip") // Better compression ratio

315

setBody(largeFile)

316

}

317

```

318

319

### Memory-Efficient Streaming

320

321

```kotlin

322

import io.ktor.utils.io.*

323

324

suspend fun streamingCompressedUpload(dataChannel: ByteReadChannel) {

325

client.post("/streaming-upload") {

326

compress("gzip")

327

setBody(object : OutgoingContent.ReadChannelContent() {

328

override fun readFrom(): ByteReadChannel = dataChannel

329

override val contentLength: Long? = null // Unknown length for streaming

330

})

331

}

332

}

333

```

334

335

## Integration Examples

336

337

### File Upload Service

338

339

```kotlin

340

class FileUploadService(private val client: HttpClient) {

341

342

suspend fun uploadFile(filename: String, content: ByteArray): Boolean {

343

return try {

344

val response = client.post("/files/upload") {

345

compress("gzip")

346

contentType(ContentType.Application.OctetStream)

347

header("X-Filename", filename)

348

setBody(content)

349

}

350

response.status.isSuccess()

351

} catch (e: Exception) {

352

false

353

}

354

}

355

356

suspend fun uploadJson(data: Any): Boolean {

357

return try {

358

val response = client.post("/api/data") {

359

compress("gzip")

360

contentType(ContentType.Application.Json)

361

setBody(data)

362

}

363

response.status.isSuccess()

364

} catch (e: Exception) {

365

false

366

}

367

}

368

}

369

```

370

371

### Batch Data Upload

372

373

```kotlin

374

suspend fun uploadBatchData(records: List<DataRecord>) {

375

val jsonData = Json.encodeToString(records)

376

377

client.post("/batch-upload") {

378

compress("gzip") // JSON compresses very well

379

contentType(ContentType.Application.Json)

380

setBody(jsonData)

381

}

382

}

383

```

384

385

### API Client with Smart Compression

386

387

```kotlin

388

class ApiClient(private val client: HttpClient) {

389

390

suspend fun createResource(resource: Resource): Resource {

391

val response = client.post("/resources") {

392

// Compress JSON payloads

393

compress("gzip")

394

contentType(ContentType.Application.Json)

395

setBody(resource)

396

}

397

return response.body<Resource>()

398

}

399

400

suspend fun uploadDocument(document: ByteArray, mimeType: ContentType): String {

401

val response = client.post("/documents") {

402

// Compress based on content type

403

when (mimeType.contentType) {

404

"text", "application" -> compress("gzip")

405

else -> {

406

// Don't compress binary formats that are already compressed

407

}

408

}

409

contentType(mimeType)

410

setBody(document)

411

}

412

return response.body<String>()

413

}

414

}

415

```

416

417

## Complete Example

418

419

```kotlin

420

import io.ktor.client.*

421

import io.ktor.client.plugins.compression.*

422

import io.ktor.client.request.*

423

import io.ktor.http.*

424

425

suspend fun main() {

426

val client = HttpClient {

427

install(ContentEncoding) {

428

mode = ContentEncodingConfig.Mode.All

429

gzip()

430

deflate()

431

}

432

}

433

434

// Small payload - no compression

435

val smallData = "Small payload"

436

client.post("/small") {

437

setBody(smallData)

438

}

439

440

// Large text payload - gzip compression

441

val largeText = "Large text payload...".repeat(1000)

442

client.post("/large-text") {

443

compress("gzip")

444

contentType(ContentType.Text.Plain)

445

setBody(largeText)

446

}

447

448

// JSON data - gzip compression

449

val jsonData = """{"users": [...], "data": [...]}"""

450

client.post("/json-upload") {

451

compress("gzip")

452

contentType(ContentType.Application.Json)

453

setBody(jsonData)

454

}

455

456

// Binary data - deflate compression

457

val binaryData = ByteArray(10000) { it.toByte() }

458

client.post("/binary-upload") {

459

compress("deflate")

460

contentType(ContentType.Application.OctetStream)

461

setBody(binaryData)

462

}

463

464

// Multi-layer compression for maximum compression

465

val criticalData = "Critical data requiring maximum compression"

466

client.post("/critical") {

467

compress("deflate", "gzip") // Double compression

468

setBody(criticalData)

469

}

470

471

client.close()

472

}

473

```