How to read a streaming request body

View Source

Problem

The request body is too large to buffer, or you want to process it incrementally as bytes arrive.

Solution

When livery_req:body/1 returns {stream, Reader}, drain it via livery_body:read/2 or livery_body:read_all/2:

upload(Req) ->
    {stream, R0} = livery_req:body(Req),
    consume(R0).

consume(R) ->
    case livery_body:read(R, 5_000) of
        {ok, Chunk, R1} ->
            ok = store:append(Chunk),
            consume(R1);
        {done, _R1} ->
            livery_resp:empty(204);
        {error, timeout, _} ->
            livery_resp:text(408, <<"slow client">>);
        {error, {client_reset, _}, _} ->
            livery_resp:empty(499)
    end.

Read everything at once

case livery_body:read_all(R0, 30_000) of
    {ok, Bytes, _R1}    -> use(Bytes);
    {error, Reason, _R} -> livery_resp:text(400, atom_to_binary(Reason))
end.

Discard the rest

If the handler decides to short-circuit (auth failure, validation), drop the remaining body so the adapter does not stall:

{ok, _R1} = livery_body:discard(R0, 1_000),
livery_resp:text(401, <<"nope">>).

Cap the size

Combine with livery_body_limit (buffered only today) or call livery_body:read/2 with a maximum byte count tracked yourself.

Backpressure

livery_body:signal_demand(R, N) hints the adapter that the handler is ready for N more bytes. The H1/H2/H3 adapters translate this into engine-level window updates. This is a no-op for the test adapter; the H1 adapter wires it to h1's read size.

See also