livery_body (livery v0.13.0)
View SourceStreaming request-body reader.
The adapter delivers body chunks, trailers, end-of-body, and reset notifications as messages to the per-request process:
{livery_body, Ref, {data, IoData}}{livery_body, Ref, {trailers, Headers}}{livery_body, Ref, eof}{livery_body, Ref, {reset, Reason}}
A reader is a small value held by the handler that knows the
stream reference and tracks terminal state. read/2 returns the
next chunk, blocking on the mailbox up to a caller-supplied
timeout. read_all/1,2 drains the entire body.
Backpressure
A reader built with a source (the adapter's translator) gives credit
back for every chunk read/2 hands out, by sending
{livery_body_demand, Ref, Bytes} to the source. The adapter turns it
into its wire library's flow control, so a handler that reads slowly
holds the client back to one flow window instead of letting the body
pile up in its mailbox. Nothing is needed in handler code. HTTP/1.1,
HTTP/2 and HTTP/3 all do this.
Summary
Functions
Account Chunk against a running byte total and a ceiling.
Drop the remainder of the body.
discard/1 with an explicit per-chunk timeout.
The reader with a byte limit: once more than Max bytes have been read
through it, read/2 returns {error, body_too_large, _}, and keeps
returning it. A limit already set is only ever lowered.
Reader with a fresh reference and no demand source.
Reader for the given reference, no demand source.
Reader bound to a reference and an adapter source pid.
Read one chunk from the body, blocking up to Timeout.
Drain the entire body, returning the concatenated bytes.
read_all/1 with an explicit per-chunk timeout (16 MiB cap).
read_all/2 with an explicit byte cap (infinity disables it).
Deprecated: read/2 already gives credit back for every chunk it
hands out (see the module docs).
Types
Functions
-spec account(non_neg_integer() | aborted, iodata(), non_neg_integer() | infinity) -> {ok, non_neg_integer()} | over | aborted.
Account Chunk against a running byte total and a ceiling.
Used by the adapter translators to bound how much request body they
forward into the per-request worker's mailbox. Returns {ok, NewTotal}
while under Max, over once the ceiling is exceeded, and threads an
aborted sentinel through once the stream has been cut so later chunks
are ignored. Max may be infinity to disable the ceiling.
Drop the remainder of the body.
discard/1 with an explicit per-chunk timeout.
-spec limit(reader(), non_neg_integer()) -> reader().
The reader with a byte limit: once more than Max bytes have been read
through it, read/2 returns {error, body_too_large, _}, and keeps
returning it. A limit already set is only ever lowered.
-spec new() -> reader().
Reader with a fresh reference and no demand source.
Reader for the given reference, no demand source.
Reader bound to a reference and an adapter source pid.
-spec read(reader(), timeout()) -> read_result().
Read one chunk from the body, blocking up to Timeout.
-spec read_all(reader()) -> {ok, binary(), reader()} | {error, error_reason(), reader()}.
Drain the entire body, returning the concatenated bytes.
Buffers at most 16 MiB by default; a larger body yields
{error, {limit, max_size}, _} so a handler reading an unbounded client
body cannot exhaust memory. Use read_all/3 to raise or disable the cap.
-spec read_all(reader(), timeout()) -> {ok, binary(), reader()} | {error, error_reason(), reader()}.
read_all/1 with an explicit per-chunk timeout (16 MiB cap).
-spec read_all(reader(), timeout(), non_neg_integer() | infinity) -> {ok, binary(), reader()} | {error, error_reason(), reader()}.
read_all/2 with an explicit byte cap (infinity disables it).
-spec signal_demand(reader(), non_neg_integer()) -> ok.
Deprecated: read/2 already gives credit back for every chunk it
hands out (see the module docs).
Sends N bytes of credit to the reader's source. The wire libraries
never grant more than was received, so a call is harmless, but it is
never needed.