Class HttpHeaderParser
- java.lang.Object
-
- akka.http.impl.engine.parsing.HttpHeaderParser
-
public final class HttpHeaderParser extends java.lang.Object
INTERNAL APIProvides for time- and space-efficient parsing of an HTTP header line in an HTTP message. It keeps a cache of all headers encountered in a previous request, so as to avoid reparsing and recreation of header model instances. For the life-time of one HTTP connection an instance of this class is owned by the connection, i.e. not shared with other connections. After the connection is closed it may be used by subsequent connections.
The core of this parser/cache is a mutable space-efficient ternary trie (prefix tree) structure, whose data are split across three arrays. The tree supports node addition and update, but no deletion (i.e. we never remove entries).
The
nodes
array keeps the main data of the trie nodes. One node is formed of a char (2 bytes) of which the LSB (least significant byte) is an ASCII octet and the MSB either 0 or an index into thebranchData
array. There are three types of nodes:1. Simple nodes: non-branching, non-leaf nodes (the most frequent kind of node) have an MSB of zero and exactly one logical sub-node which is the next node in the
nodes
array (i.e. the one at index n + 1). 2. Branching nodes: have 2 or three children and a non-zero MSB. (MSB value - 1)*3 is the row index into thebranchData
array, which contains the branching data. 3. Leaf nodes: have no sub-nodes and no character value. They merely "stop" the node chain and point to a value. The LSB of leaf nodes is zero and the (MSB value - 1) is an index into the values array.This design has the following consequences: - Since only leaf nodes can have values the trie cannot store keys that are prefixes of other stored keys. - If the trie stores n values it has less than n branching nodes (adding the first value does not create a branching node, the addition of every subsequent value creates at most one additional branching node). - If the trie has n branching nodes it stores at least n * 2 and at most n * 3 values.
The
branchData
array keeps the branching data for branching nodes in the trie. It's a flattened two-dimensional array with a row consisting of the following 3 signed 16-bit integers: row-index + 0: if non-zero: index into thenodes
array for the "lesser" child of the node row-index + 1: if non-zero: index into thenodes
array for the "equal" child of the node row-index + 2: if non-zero: index into thenodes
array for the "greater" child of the node The array has a fixed size of 254 rows (since we can address at most 256 - 1 values with the node MSB and we always have fewer branching nodes than values).The
values
array contains the payload data addressed by trie leaf nodes. Since we address them via the nodes MSB and zero is reserved the trie cannot hold more then 255 items, so this array has a fixed size of 255.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
HttpHeaderParser.HeaderValueParser
static class
HttpHeaderParser.ModeledHeaderValueParser
static class
HttpHeaderParser.RawHeaderValueParser
static class
HttpHeaderParser.Settings
INTERNAL API
-
Constructor Summary
Constructors Constructor Description HttpHeaderParser()
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description static HttpHeaderParser
apply(HttpHeaderParser.Settings settings, akka.event.LoggingAdapter log)
scala.collection.immutable.Map<java.lang.String,java.lang.Object>
contentHistogram()
Returns the number of header values stored per header type.HttpHeaderParser
createShallowCopy()
Returns a copy of this parser that shares the trie data with this instance.static scala.Function1<ErrorInfo,scala.runtime.BoxedUnit>
defaultIllegalHeaderHandler(HttpHeaderParser.Settings settings, akka.event.LoggingAdapter log)
static scala.runtime.Nothing$
fail(java.lang.String summary, StatusCode status)
java.lang.String
formatRawTrie()
Returns a string representation of the raw trie data.java.lang.String
formatSizes()
Returns a string representation of the trie structure size.java.lang.String
formatTrie()
Renders the trie structure into an ASCII representation.static void
insert(HttpHeaderParser parser, akka.util.ByteString input, java.lang.Object value)
static void
insertRemainingCharsAsNewNodes(HttpHeaderParser parser, akka.util.ByteString input, java.lang.Object value)
boolean
isEmpty()
akka.event.LoggingAdapter
log()
int
parseHeaderLine(akka.util.ByteString input, int lineStart, int cursor, int nodeIx)
Parses a header line and returns the line start index of the subsequent line.static HttpHeaderParser
prime(HttpHeaderParser parser)
HttpHeader
resultHeader()
Contains the parsed header instance after a call toparseHeaderLine
.HttpHeaderParser.Settings
settings()
static HttpHeaderParser
unprimed(HttpHeaderParser.Settings settings, akka.event.LoggingAdapter log, scala.Function1<ErrorInfo,scala.runtime.BoxedUnit> warnOnIllegalHeader)
-
-
-
Method Detail
-
apply
public static HttpHeaderParser apply(HttpHeaderParser.Settings settings, akka.event.LoggingAdapter log)
-
defaultIllegalHeaderHandler
public static scala.Function1<ErrorInfo,scala.runtime.BoxedUnit> defaultIllegalHeaderHandler(HttpHeaderParser.Settings settings, akka.event.LoggingAdapter log)
-
unprimed
public static HttpHeaderParser unprimed(HttpHeaderParser.Settings settings, akka.event.LoggingAdapter log, scala.Function1<ErrorInfo,scala.runtime.BoxedUnit> warnOnIllegalHeader)
-
prime
public static HttpHeaderParser prime(HttpHeaderParser parser)
-
insert
public static void insert(HttpHeaderParser parser, akka.util.ByteString input, java.lang.Object value)
-
insertRemainingCharsAsNewNodes
public static void insertRemainingCharsAsNewNodes(HttpHeaderParser parser, akka.util.ByteString input, java.lang.Object value)
-
fail
public static scala.runtime.Nothing$ fail(java.lang.String summary, StatusCode status)
-
settings
public HttpHeaderParser.Settings settings()
-
log
public akka.event.LoggingAdapter log()
-
resultHeader
public HttpHeader resultHeader()
Contains the parsed header instance after a call toparseHeaderLine
.- Returns:
- (undocumented)
-
isEmpty
public boolean isEmpty()
-
createShallowCopy
public HttpHeaderParser createShallowCopy()
Returns a copy of this parser that shares the trie data with this instance.- Returns:
- (undocumented)
-
parseHeaderLine
public int parseHeaderLine(akka.util.ByteString input, int lineStart, int cursor, int nodeIx)
Parses a header line and returns the line start index of the subsequent line. The parsed header instance is written to theresultHeader
member. If the trie still has space for this type of header (and as a whole) the parsed header is cached. Throws aNotEnoughDataException
if the given input doesn't contain enough data to fully parse the given header line. Note that there must be at least one byte available after a CRLF sequence, in order to distinguish a true line ending from a line fold. If the header is invalid a respectiveParsingException
is thrown.- Parameters:
input
- (undocumented)lineStart
- (undocumented)cursor
- (undocumented)nodeIx
- (undocumented)- Returns:
- (undocumented)
-
formatTrie
public java.lang.String formatTrie()
Renders the trie structure into an ASCII representation.- Returns:
- (undocumented)
-
contentHistogram
public scala.collection.immutable.Map<java.lang.String,java.lang.Object> contentHistogram()
Returns the number of header values stored per header type.- Returns:
- (undocumented)
-
formatRawTrie
public java.lang.String formatRawTrie()
Returns a string representation of the raw trie data.- Returns:
- (undocumented)
-
formatSizes
public java.lang.String formatSizes()
Returns a string representation of the trie structure size.- Returns:
- (undocumented)
-
-