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 downloadChunks = 0;
var downloadBytes = 0;
var downloaded = await client
    .Get($"/rooms/{room.Body}/export")
    .DownloadAsync(chunk =>
    {
        downloadChunks++;
        downloadBytes += chunk.Length;
    });
Console.WriteLine($"download stream: chunks {downloadChunks} bytes {downloadBytes}");

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.

var uploadChunks = new Queue<byte[]>(
    new[]
    {
        Encoding.UTF8.GetBytes("{\"playerId\":\"p2\",\"text\":\"one\"}\n"),
        Encoding.UTF8.GetBytes("{\"playerId\":\"p2\",\"text\":\"two\"}\n"),
        Encoding.UTF8.GetBytes("{\"playerId\":\"p2\",\"text\":\"three\"}\n"),
    }
);
var imported = await client
    .Post($"/rooms/{room.Body}/import")
    .BodyStream(
        () => uploadChunks.Count > 0 ? uploadChunks.Dequeue() : null,
        "application/x-ndjson"
    )
    .Async<ImportResponse>();
Console.WriteLine($"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.