Class RequestBody

java.lang.Object
dev.relism.flash.models.RequestBody

public class RequestBody extends Object
Accessor for the HTTP request body. Supports two mutually exclusive read modes per request:
  • bytes() — materialises the full body into a byte[] and caches it. Safe to call multiple times; the second call returns the cached array. Throws for bodies larger than 2 GB.
  • stream() — returns a bounded InputStream without upfront allocation. into the already-buffered header bytes stitched to the socket; for chunked bodies it is the raw ChunkedInputStream that de-chunks on the fly.

Mutual exclusivity: calling both bytes() and stream() on the same request produces undefined results. Choose one mode per handler.

Keep-alive: unread body bytes are discarded by Request.drain() after the handler returns so the socket is correctly positioned for the next pipelined request. One instance per connection (owned by RequestParser, repositioned via reset(java.io.InputStream, long, byte[], int, int) for every request), the same treatment Request/RequestLine get. The of(byte[]) factory below remains for test/manual construction and returns a freestanding, unpooled instance — exactly like Request's own manual constructor. stream() used to allocate a SequenceInputStream, a ByteArrayInputStream and an anonymous bounded InputStream on every call. It now hands out one persistent RequestBody.BoundedBufferedInputStream, repositioned per request instead of reallocated. drain()'s chunked-body path used to call InputStream.transferTo, which allocates a fresh 8 KiB byte[] internally on every call (the JDK default implementation); it now drains through a lazily-created, persistent buffer instead.

  • Constructor Details

  • Method Details

    • reset

      public void reset(InputStream socket, long contentLength, byte[] preBuf, int preBufOff, int preBufLen)
      Repositions this instance over a new request. public because RequestParser (a different package) owns and resets its own pooled instance directly — matching RequestLine.reset(dev.relism.flash.http.HttpMethod, dev.relism.fpr.core.ByteView, dev.relism.fpr.core.ByteView, dev.relism.fpr.core.ByteView, dev.relism.flash.models.HeaderView)'s precedent — not because user code should ever call it.
    • isEmpty

      public boolean isEmpty()
      true if the body has zero bytes (Content-Length: 0 or no body).
    • contentLength

      public long contentLength()
      Declared body size in bytes. Returns -1 for Transfer-Encoding: chunked bodies where the size is not known upfront.
    • fullyRead

      public boolean fullyRead()
      Whether the complete body has been consumed by the application.
    • bytes

      public byte[] bytes()
      Materialises and caches the full body. Suitable for JSON, small form data, and any payload that must be inspected in full. The result is cached — repeated calls return the same array.

      For chunked bodies (contentLength() == -1), reads until the chunked stream signals EOF.

      Throws:
      IllegalStateException - if contentLength() exceeds Integer.MAX_VALUE (~2 GB); use stream() for large bodies instead
    • stream

      public InputStream stream()
      Returns a bounded InputStream over the body without upfront allocation.

      For fixed-length bodies: a reused RequestBody.BoundedBufferedInputStream (see the class view of the socket stream — zero allocation on a warm connection.

      For chunked bodies: the raw ChunkedInputStream that de-chunks on the fly; EOF signals the end of the logical body and leaves the socket positioned for the next keep-alive request.

      If bytes() was called first, returns a fresh ByteArrayInputStream