Skip to content

Streaming

Contents | Previous: Authentication, TLS, and Proxy | Next: Client and Request Lifecycle

After reading this chapter

This chapter processes a response in chunks and sends a request body in parts. Its code comes from each language's HttpClient tutorial.

Streaming moves a large body through a caller callback or provider. Unlike a JSON body, it does not serialize or accumulate the whole body. Response Rules covers status and compression rules.

↗ 크게 보기

The provider and sink are each consumed once while the body moves. This is why the streaming path does not apply replay or transparent decompression.

1. Response Chunks Flow Through a Download Sink

A download sink is a callback invoked for each received body chunk. A raw response carries status, headers, and the body before JSON decoding. The final raw response from a download preserves status and headers; bodies from intermediate redirect responses do not reach the sink.

var chunks = 0
var bytes = 0
client.get("/rooms/$roomId/export").awaitDownload { chunk ->
    chunks += 1
    bytes += chunk.size
}
println("download stream: chunks $chunks bytes $bytes")

The example counts each export-body chunk and accumulates the total number of chunks and bytes.

2. Request Chunks Come from a Body Stream Provider

A body stream provider returns the next chunk to send and signals completion with the language's empty value. Its configuration includes the content type.

val lines =
    listOf(
        "{\"playerId\":\"p2\",\"text\":\"import-1\"}\n".toByteArray(StandardCharsets.UTF_8),
        "{\"playerId\":\"p2\",\"text\":\"import-2\"}\n".toByteArray(StandardCharsets.UTF_8),
        "{\"playerId\":\"p2\",\"text\":\"import-3\"}\n".toByteArray(StandardCharsets.UTF_8),
    )
var nextLine = 0
val imported =
    client
        .post("/rooms/$roomId/import")
        .bodyStream(
            Supplier { if (nextLine < lines.size) lines[nextLine++] else null },
            "application/x-ndjson",
        )
        .await<Imported>()
println("upload stream: imported ${imported.body.imported}")

The example supplies three NDJSON lines in sequence and confirms that the server imported three items.

3. Retry and Decompression Are Excluded

A download sink and a body stream provider consume their body once and cannot recreate it. A streaming request is therefore excluded from retry and redirect replay. A download sink receives compressed response bytes unchanged; decompression is not applied.

4. Next Chapter

Client and Request Lifecycle covers client reuse, close timing, response completion, and timeout boundaries.