Files
Flash5/docs/lifecycle/request/BODY.md
T

3.0 KiB

Request Body

req.body() returns a RequestBody — a lazy accessor that exposes the HTTP request body in two mutually exclusive modes. Choose one per handler based on the payload size and how you intend to consume it.


Two modes

bytes() — materialise

byte[] body = req.body().bytes();

Reads the full body into a byte[] and caches the result. Safe to call multiple times — the second call returns the same cached array, no I/O is performed again.

Use for:

  • JSON parsing (new String(body, UTF_8) then parse)
  • Small form data
  • Any payload that must be inspected in full before responding

Limit: throws IllegalStateException if Content-Length exceeds Integer.MAX_VALUE (~2 GB). For larger bodies use stream().

Chunked bodies: reads until ChunkedInputStream signals EOF, then caches.


stream() — zero-copy

InputStream in = req.body().stream();

Returns a bounded InputStream without allocating the full body upfront.

Use for:

  • Large file uploads
  • Bodies passed directly to disk, a database, or another stream
  • Multipart parsing (via Multipart.of(req) which calls this internally)

Fixed-length bodies: a SequenceInputStream of any pre-buffered header bytes (from the RequestParser read buffer, already in memory) followed by a bounded view of the socket stream. The small pre-buffered slice costs nothing extra.

Chunked bodies: returns the raw ChunkedInputStream directly. It de-chunks on the fly — reads the hex chunk-size line, the data, and the trailing CRLF — and signals EOF at the end of the last chunk, leaving the socket positioned correctly for the next keep-alive request.

After bytes(): if the body was already materialised, stream() returns a fresh ByteArrayInputStream over the cached array. No I/O is performed.


Mutual exclusivity

// SAFE — pick one mode
byte[]      b = req.body().bytes();
InputStream s = req.body().stream();

// UNSAFE — bytes() then stream() is safe (stream() wraps the cache)
// UNSAFE — stream() partially read, then bytes() → undefined results

The rule: if you call stream() first and partially read it, calling bytes() afterwards will either throw (if contentLength > 2 GB) or read only the remaining socket bytes into the array, missing the already-consumed portion.


Checking the size

long size = req.body().contentLength();
  • > 0 — fixed-length body; exact byte count
  • == 0 — empty body (Content-Length: 0 or no body present)
  • == -1Transfer-Encoding: chunked; size is unknown upfront
boolean empty = req.body().isEmpty(); // true when contentLength == 0

Decision guide

Payload size Encoding Use
< 2 GB, fully needed any bytes()
Any size, pass-through any stream()
Multipart form any Multipart.of(req) (uses stream() internally)
Size unknown chunked stream()