Class Http1Limits

java.lang.Object
dev.relism.flash.http.Http1Limits

public final class Http1Limits extends Object
Bounds the HTTP/1.1 parser (RequestParser, ChunkedInputStream) enforces against a peer's input, in one place. against a named constant here — never against an ad-hoc literal, and never by letting the underlying buffer throw on overrun. Each field's Javadoc names the specific attack it bounds. Compare dev.relism.flash.http2.Http2Limits, the HTTP/2 equivalent.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final int
    buffer as the response head (status line + headers) and written with it in a single OutputStream.write call; larger bodies are written in a second write right after the head, since copying a large body into the head buffer first would cost more (an extra full-body memcpy) than the syscall it saves. 8 KiB — matches this codebase's other "one socket-buffer's worth" constants (ConnectionScratch.RELAY_BUFFER_SIZE, BufferedByteSource.DEFAULT_BUFFER_SIZE) rather than introducing an uncalibrated
    static final int
    Maximum length, in bytes, of the chunk-extension section (the optional ;name=value data after a chunk size and before its CRLF, RFC 9112 §7.1.1).
    static final long
    Maximum size, in bytes, of a single Transfer-Encoding: chunked chunk.
    static final int
    Maximum number of chunks accepted in a single request body.
    static final long
    The largest Content-Length value accepted, in bytes.
    static final int
    Maximum number of header lines accepted in a single request.
    static final int
    Maximum length, in bytes, of a single header field name.
    static final int
    Maximum length, in bytes, of a single header field value.
    static final long
    buffers eagerly into a byte[] — text fields (always buffered) and, during a full parts()/parts(String) scan, file bodies too.
    static final int
    header block.
    static final int
    Content-Type, …) accepted per multipart part.
    static final int
    multipart/form-data body.
    static final int
    Maximum length, in bytes, of the request line (METHOD SP target SP version).
    static final int
    Maximum combined size, in bytes, of every response header's name + value bytes (Response.header(...)'s growable headerRegion).
    static final int
    Maximum number of Response.header(...) calls (any overload) accepted on a single response.
    static final int
    Maximum number of trailer header lines accepted after the final chunk of a chunked body (RFC 9112 §7.1.2).
  • Method Summary

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • MAX_CONTENT_LENGTH

      public static final long MAX_CONTENT_LENGTH
      The largest Content-Length value accepted, in bytes. RFC 9112 places no upper bound on the header's numeric value, but an unbounded value from a hostile peer is a resource-exhaustion vector for any code path that pre-sizes a buffer from it. Requests declaring a length above this are rejected with 413 Payload Too Large before any body byte is read.

      4 GiB — generous enough for legitimate large uploads (Flash is a general-purpose server, not an API-only framework with a tiny default), while still bounding a hostile peer to a finite, known-in-advance number rather than the effectively unbounded Long.MAX_VALUE the parser accepted before this limit existed. Comfortably above Integer.MAX_VALUE (~2.1 billion) so legitimate very-large declared lengths are

      See Also:
    • MAX_HEADER_COUNT

      public static final int MAX_HEADER_COUNT
      Maximum number of header lines accepted in a single request. Without this bound, a request with tens of thousands of one-byte headers passes the total header-block size check (maxHeaderBufferSize) while still forcing every subsequent Http1HeaderMap lookup to scan all of them — turning a small request into quadratic CPU
      See Also:
    • MAX_HEADER_NAME_LENGTH

      public static final int MAX_HEADER_NAME_LENGTH
      Maximum length, in bytes, of a single header field name. RFC 9110 §5.1 places no formal limit; this bound exists purely to cap per-header memory and scan cost.
      See Also:
    • MAX_HEADER_VALUE_LENGTH

      public static final int MAX_HEADER_VALUE_LENGTH
      Maximum length, in bytes, of a single header field value. Bounds per-header memory and scan cost the same way MAX_HEADER_NAME_LENGTH bounds the name.
      See Also:
    • MAX_REQUEST_LINE_LENGTH

      public static final int MAX_REQUEST_LINE_LENGTH
      Maximum length, in bytes, of the request line (METHOD SP target SP version). Tracked separately from the overall header-buffer size so an oversized request line is rejected with a specific, correct status (414 URI Too Long) rather than folded into the generic header-block-too-large case.
      See Also:
    • MAX_CHUNK_SIZE

      public static final long MAX_CHUNK_SIZE
      Maximum size, in bytes, of a single Transfer-Encoding: chunked chunk. ChunkedInputStream.readChunkSize previously accepted any value up to 2 GiB before rejecting it; a hostile peer can advertise a huge chunk size and then trickle bytes, forcing the connection to stay open far longer than any legitimate chunk would need (bounded separately by bodyReadTimeoutMs, but this limit catches the size claim itself before that timeout would).
      See Also:
    • MAX_CHUNK_EXT_LENGTH

      public static final int MAX_CHUNK_EXT_LENGTH
      Maximum length, in bytes, of the chunk-extension section (the optional ;name=value data after a chunk size and before its CRLF, RFC 9112 §7.1.1). Flash does not interpret chunk extensions; without a bound, a peer could send an arbitrarily long extension on every chunk purely to waste CPU discarding it.
      See Also:
    • MAX_CHUNKS_PER_BODY

      public static final int MAX_CHUNKS_PER_BODY
      Maximum number of chunks accepted in a single request body. Without this bound, a peer can send an unbounded number of minimal (or zero-length) chunks, each cheap individually but collectively forcing unbounded per-chunk framing work — a "death by a thousand chunks" variant of a slow-body attack.
      See Also:
    • MAX_TRAILER_COUNT

      public static final int MAX_TRAILER_COUNT
      Maximum number of trailer header lines accepted after the final chunk of a chunked body (RFC 9112 §7.1.2). Bounded for the same reason MAX_HEADER_COUNT bounds the regular header section; trailer values are separately bounded by MAX_HEADER_VALUE_LENGTH.
      See Also:
    • INLINE_BODY_THRESHOLD

      public static final int INLINE_BODY_THRESHOLD
      buffer as the response head (status line + headers) and written with it in a single OutputStream.write call; larger bodies are written in a second write right after the head, since copying a large body into the head buffer first would cost more (an extra full-body memcpy) than the syscall it saves. 8 KiB — matches this codebase's other "one socket-buffer's worth" constants (ConnectionScratch.RELAY_BUFFER_SIZE, BufferedByteSource.DEFAULT_BUFFER_SIZE) rather than introducing an uncalibrated
      See Also:
    • MAX_MULTIPART_PARTS

      public static final int MAX_MULTIPART_PARTS
      multipart/form-data body. Without this bound, a peer can send an unbounded number of minimal parts — each cheap individually but forcing unbounded growth of the parser's scanned list and unbounded per-part header-parsing work, the multipart analogue of MAX_CHUNKS_PER_BODY.
      See Also:
    • MAX_MULTIPART_PART_HEADER_COUNT

      public static final int MAX_MULTIPART_PART_HEADER_COUNT
      Content-Type, …) accepted per multipart part. Real clients send at most two or three; without a bound a peer could send an effectively unlimited number before the blank line that ends a part's header block, forcing unbounded HashMap growth per part.
      See Also:
    • MAX_MULTIPART_HEADER_LINE_LENGTH

      public static final int MAX_MULTIPART_HEADER_LINE_LENGTH
      header block. Multipart.readLine otherwise has no bound of its own to fall back on — unlike the top-level HTTP headers (bounded by MAX_HEADER_VALUE_LENGTH in RequestParser), a line here with no \r\n would grow its StringBuilder without limit for as long as the peer keeps streaming bytes.
      See Also:
    • MAX_MULTIPART_BUFFERED_PART_SIZE

      public static final long MAX_MULTIPART_BUFFERED_PART_SIZE
      buffers eagerly into a byte[] — text fields (always buffered) and, during a full parts()/parts(String) scan, file bodies too. MAX_CONTENT_LENGTH bounds the whole request body, but at 4 GiB (and effectively unbounded for a chunked body, see MAX_CHUNKS_PER_BODY × MAX_CHUNK_SIZE) it does nothing to stop a single part from exhausting the heap on its own — this is the bound that actually protects ByteArrayOutputStream-style eager buffering. Deliberately does not apply to Part.materialize() on a streaming file part returned by Multipart.file() — that call is documented as an explicit, opt-in heap allocation the caller chooses to pay for.
      See Also:
    • MAX_RESPONSE_HEADER_BYTES

      public static final int MAX_RESPONSE_HEADER_BYTES
      Maximum combined size, in bytes, of every response header's name + value bytes (Response.header(...)'s growable headerRegion). Unlike every other bound in this class, this one guards against a bug in Flash's own caller rather than a hostile peer — a handler that calls header(...) in an unbounded loop (e.g. echoing an unbounded collection into headers) would otherwise grow this connection's scratch region without limit for the rest of its lifetime, since it is never shrunk back down between
      See Also:
    • MAX_RESPONSE_HEADER_COUNT

      public static final int MAX_RESPONSE_HEADER_COUNT
      Maximum number of Response.header(...) calls (any overload) accepted on a single response. Same rationale as MAX_RESPONSE_HEADER_BYTES: bounds the response-side analogue of MAX_HEADER_COUNT, since an unbounded call count grows the header index arrays even if each individual header is small.
      See Also: