How to read a streaming request body
View SourceProblem
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
- Reference:
livery_body - Concepts: Streaming and backpressure