Package dev.relism.flash.http
Class Http1Limits
java.lang.Object
dev.relism.flash.http.Http1Limits
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
FieldsModifier and TypeFieldDescriptionstatic final intbuffer as the response head (status line + headers) and written with it in a singleOutputStream.writecall; larger bodies are written in a secondwriteright 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 uncalibratedstatic final intMaximum length, in bytes, of the chunk-extension section (the optional;name=valuedata after a chunk size and before its CRLF, RFC 9112 §7.1.1).static final longMaximum size, in bytes, of a singleTransfer-Encoding: chunkedchunk.static final intMaximum number of chunks accepted in a single request body.static final longThe largestContent-Lengthvalue accepted, in bytes.static final intMaximum number of header lines accepted in a single request.static final intMaximum length, in bytes, of a single header field name.static final intMaximum length, in bytes, of a single header field value.static final longbuffers eagerly into abyte[]— text fields (always buffered) and, during a fullparts()/parts(String)scan, file bodies too.static final intheader block.static final intContent-Type, …) accepted per multipart part.static final intmultipart/form-databody.static final intMaximum length, in bytes, of the request line (METHOD SP target SP version).static final intMaximum combined size, in bytes, of every response header's name + value bytes (Response.header(...)'s growableheaderRegion).static final intMaximum number ofResponse.header(...)calls (any overload) accepted on a single response.static final intMaximum number of trailer header lines accepted after the final chunk of a chunked body (RFC 9112 §7.1.2). -
Method Summary
-
Field Details
-
MAX_CONTENT_LENGTH
public static final long MAX_CONTENT_LENGTHThe largestContent-Lengthvalue 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 with413 Payload Too Largebefore 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_VALUEthe parser accepted before this limit existed. Comfortably aboveInteger.MAX_VALUE(~2.1 billion) so legitimate very-large declared lengths are- See Also:
-
MAX_HEADER_COUNT
public static final int MAX_HEADER_COUNTMaximum 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 subsequentHttp1HeaderMaplookup 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_LENGTHMaximum 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_LENGTHMaximum length, in bytes, of a single header field value. Bounds per-header memory and scan cost the same wayMAX_HEADER_NAME_LENGTHbounds the name.- See Also:
-
MAX_REQUEST_LINE_LENGTH
public static final int MAX_REQUEST_LINE_LENGTHMaximum 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_SIZEMaximum size, in bytes, of a singleTransfer-Encoding: chunkedchunk.ChunkedInputStream.readChunkSizepreviously 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 bybodyReadTimeoutMs, 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_LENGTHMaximum length, in bytes, of the chunk-extension section (the optional;name=valuedata 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_BODYMaximum 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_COUNTMaximum number of trailer header lines accepted after the final chunk of a chunked body (RFC 9112 §7.1.2). Bounded for the same reasonMAX_HEADER_COUNTbounds the regular header section; trailer values are separately bounded byMAX_HEADER_VALUE_LENGTH.- See Also:
-
INLINE_BODY_THRESHOLD
public static final int INLINE_BODY_THRESHOLDbuffer as the response head (status line + headers) and written with it in a singleOutputStream.writecall; larger bodies are written in a secondwriteright 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_PARTSmultipart/form-databody. Without this bound, a peer can send an unbounded number of minimal parts — each cheap individually but forcing unbounded growth of the parser'sscannedlist and unbounded per-part header-parsing work, the multipart analogue ofMAX_CHUNKS_PER_BODY.- See Also:
-
MAX_MULTIPART_PART_HEADER_COUNT
public static final int MAX_MULTIPART_PART_HEADER_COUNTContent-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 unboundedHashMapgrowth per part.- See Also:
-
MAX_MULTIPART_HEADER_LINE_LENGTH
public static final int MAX_MULTIPART_HEADER_LINE_LENGTHheader block.Multipart.readLineotherwise has no bound of its own to fall back on — unlike the top-level HTTP headers (bounded byMAX_HEADER_VALUE_LENGTHinRequestParser), a line here with no\r\nwould grow itsStringBuilderwithout 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_SIZEbuffers eagerly into abyte[]— text fields (always buffered) and, during a fullparts()/parts(String)scan, file bodies too.MAX_CONTENT_LENGTHbounds the whole request body, but at 4 GiB (and effectively unbounded for a chunked body, seeMAX_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 protectsByteArrayOutputStream-style eager buffering. Deliberately does not apply toPart.materialize()on a streaming file part returned byMultipart.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_BYTESMaximum combined size, in bytes, of every response header's name + value bytes (Response.header(...)'s growableheaderRegion). 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 callsheader(...)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_COUNTMaximum number ofResponse.header(...)calls (any overload) accepted on a single response. Same rationale asMAX_RESPONSE_HEADER_BYTES: bounds the response-side analogue ofMAX_HEADER_COUNT, since an unbounded call count grows the header index arrays even if each individual header is small.- See Also:
-