Involved Source Filesencode.go Package hpack implements HPACK, a compression format for
efficiently representing HTTP header fields in the context of HTTP/2.
See http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09huffman.gostatic_table.gotables.go
Package-Level Type Names (total 12, in which 5 are exported)
/* sort exporteds by: | */
A Decoder is the decoding context for incremental processing of
header blocks. buf is the unparsed buffer. It's only written to
saveBuf if it was truncated in the middle of a header
block. Because it's usually not owned, we can only
process it under Write. // not owned; only valid during WritedynTabdynamicTableemitfunc(f HeaderField) // whether calls to emit are enabled // processing the first field of the header block // 0 means unlimited saveBuf is previous data passed to Write which we weren't able
to fully parse before. Unlike buf, we own this data. Close declares that the decoding is complete and resets the Decoder
to be reused again for a new header block. If there is any remaining
data in the decoder's buffer, Close returns an error. DecodeFull decodes an entire block.
TODO: remove this method and make it incremental later? This is
easier for debugging now. EmitEnabled reports whether calls to the emitFunc provided to NewDecoder
are currently enabled. The default is true. SetAllowedMaxDynamicTableSize sets the upper bound that the encoded
stream (via dynamic table size updates) may set the maximum size
to. SetEmitEnabled controls whether the emitFunc provided to NewDecoder
should be called. The default is true.
This facility exists to let servers enforce MAX_HEADER_LIST_SIZE
while still decoding and keeping in-sync with decoder state, but
without doing unnecessary decompression or generating unnecessary
garbage for header fields past the limit. SetEmitFunc changes the callback used when new header fields
are decoded.
It must be non-nil. It does not affect EmitEnabled.(*Decoder) SetMaxDynamicTableSize(v uint32) SetMaxStringLength sets the maximum size of a HeaderField name or
value string. If a string exceeds this length (even after any
decompression), Write will return ErrStringLength.
A value of 0 means unlimited and is the default from NewDecoder.(*Decoder) Write(p []byte) (n int, err error)(*Decoder) at(i uint64) (hf HeaderField, ok bool)(*Decoder) callEmit(hf HeaderField) error(*Decoder) decodeString(u undecodedString) (string, error)(*Decoder) maxTableIndex() int (same invariants and behavior as parseHeaderFieldRepr) (same invariants and behavior as parseHeaderFieldRepr) (same invariants and behavior as parseHeaderFieldRepr) returns errNeedMore if there isn't enough data available.
any other error is fatal.
consumes d.buf iff it returns nil.
precondition: must be called with len(d.buf) > 0 readString reads an hpack string from p.
It returns a reference to the encoded string data to permit deferring decode costs
until after the caller verifies all data is present.
*Decoder : internal/bisect.Writer
*Decoder : io.Closer
*Decoder : io.WriteCloser
*Decoder : io.Writer
*Decoder : crypto/tls.transcriptHash
func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decoder
buf[]bytedynTabdynamicTable maxSizeLimit is the maximum table size this encoder
supports. This will protect the encoder from too large
size. minSize is the minimum table size set by
SetMaxDynamicTableSize after the previous Header Table Size
Update. tableSizeUpdate indicates whether "Header Table Size
Update" is required.wio.Writer MaxDynamicTableSize returns the current dynamic header table size. SetMaxDynamicTableSize changes the dynamic header table size to v.
The actual size is bounded by the value passed to
SetMaxDynamicTableSizeLimit. SetMaxDynamicTableSizeLimit changes the maximum value that can be
specified in SetMaxDynamicTableSize to v. By default, it is set to
4096, which is the same size of the default dynamic header table
size described in HPACK specification. If the current maximum
dynamic header table size is strictly greater than v, "Header Table
Size Update" will be done in the next WriteField call and the
maximum dynamic header table size is truncated to v. WriteField encodes f into a single Write to e's underlying Writer.
This function may also produce bytes for "Header Table Size Update"
if necessary. If produced, it is done before encoding f. searchTable searches f in both stable and dynamic header tables.
The static header table is searched first. Only when there is no
exact match for both name and value, the dynamic header table is
then searched. If there is no match, i is 0. If both name and value
match, i is the matched index and nameValueMatch becomes true. If
only name matches, i points to that index and nameValueMatch
becomes false. shouldIndex reports whether f should be indexed.
func NewEncoder(w io.Writer) *Encoder
func net/http.http2encKV(enc *Encoder, k, v string)
func net/http.http2encodeHeaders(enc *Encoder, h http.Header, keys []string)
A HeaderField is a name-value pair. Both the name and value are
treated as opaque sequences of octets.Namestring Sensitive means that this header field should never be
indexed.Valuestring IsPseudo reports whether the header field is an http2 pseudo header.
That is, it reports whether it starts with a colon.
It is not otherwise guaranteed to be a valid pseudo header field,
though. Size returns the size of an entry per RFC 7541 section 4.1.( HeaderField) String() string
HeaderField : fmt.Stringer
HeaderField : context.stringer
HeaderField : runtime.stringer
func (*Decoder).DecodeFull(p []byte) ([]HeaderField, error)
func (*Decoder).at(i uint64) (hf HeaderField, ok bool)
func (*Encoder).WriteField(f HeaderField) error
func appendIndexedName(dst []byte, f HeaderField, i uint64, indexing bool) []byte
func appendNewName(dst []byte, f HeaderField, indexing bool) []byte
func (*Decoder).callEmit(hf HeaderField) error
func (*Encoder).searchTable(f HeaderField) (i uint64, nameValueMatch bool)
func (*Encoder).shouldIndex(f HeaderField) bool
An InvalidIndexError is returned when an encoder references a table
entry before the static table or after the end of the dynamic table.( InvalidIndexError) Error() string
InvalidIndexError : error
// maxSize may go up to this, inclusive // current maxSize // in bytes https://httpwg.org/specs/rfc7541.html#rfc.section.2.3.2(*dynamicTable) add(f HeaderField) If we're too big, evict old stuff.(*dynamicTable) setMaxSize(v uint32)
headerFieldTable implements a list of HeaderFields.
This is used to implement the static and dynamic tables. byName maps a HeaderField name to the unique id of the newest entry with
the same name. See above for a definition of "unique id". byNameValue maps a HeaderField name/value pair to the unique id of the newest
entry with the same name and value. See above for a definition of "unique id". For static tables, entries are never evicted.
For dynamic tables, entries are evicted from ents[0] and added to the end.
Each entry has a unique id that starts at one and increments for each
entry that is added. This unique id is stable across evictions, meaning
it can be used as a pointer to a specific entry. As in hpack, unique ids
are 1-based. The unique id for ents[k] is k + evictCount + 1.
Zero is not a valid unique id.
evictCount should not overflow in any remotely practical situation. In
practice, we will have one dynamic table per HTTP/2 connection. If we
assume a very powerful server that handles 1M QPS per connection and each
request adds (then evicts) 100 entries from the table, it would still take
2M years for evictCount to overflow.evictCountuint64 addEntry adds a new entry. evictOldest evicts the n oldest entries in the table. idToIndex converts a unique id to an HPACK index.
See Section 2.3.3.(*headerFieldTable) init() len reports the number of entries in the table. search finds f in the table. If there is no match, i is 0.
If both name and value match, i is the matched index and nameValueMatch
becomes true. If only name matches, i points to that index and
nameValueMatch becomes false.
The returned index is a 1-based HPACK index. For dynamic tables, HPACK says
that index 1 should be the newest entry, but t.ents[0] is the oldest entry,
meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic
table, the return value i actually refers to the entry t.ents[t.len()-i].
All tables are assumed to be a dynamic tables except for the global staticTable.
See Section 2.3.3.
var staticTable *headerFieldTable
incomparable is a zero-width, non-comparable type. Adding it to a struct
makes that struct also non-comparable, and generally doesn't add
any size (as long as it's first).
children is non-nil for internal nodes The following are only valid if children is nil: // number of bits that led to the output of sym // output symbol
func getRootHuffmanNode() *node
func newInternalNode() *node
var lazyRootHuffmanNode *node
Package-Level Functions (total 18, in which 6 are exported)
AppendHuffmanString appends s, as encoded in Huffman codes, to dst
and returns the extended buffer.
HuffmanDecode decodes the string in v and writes the expanded
result to w, returning the number of bytes written to w and the
Write call's return value. At most one Write call is made.
HuffmanDecodeToString decodes the string in v.
HuffmanEncodeLength returns the number of bytes required to encode
s in Huffman codes. The result is round up to byte boundary.
NewDecoder returns a new decoder with the provided maximum dynamic
table size. The emitFunc will be called for each valid field
parsed, in the same goroutine as calls to Write, before Write returns.
NewEncoder returns a new Encoder which performs HPACK encoding. An
encoded data is written to w.
appendHpackString appends s, as encoded in "String Literal"
representation, to dst and returns the extended buffer.
s will be encoded in Huffman codes only when it produces strictly
shorter byte string.
appendIndexed appends index i, as encoded in "Indexed Header Field"
representation, to dst and returns the extended buffer.
appendIndexedName appends f and index i referring indexed name
entry, as encoded in one of "Literal Header field - Indexed Name"
representation variants, to dst and returns the extended buffer.
If f.Sensitive is true, "Never Indexed" representation is used. If
f.Sensitive is false and indexing is true, "Incremental Indexing"
representation is used.
appendNewName appends f, as encoded in one of "Literal Header field
- New Name" representation variants, to dst and returns the
extended buffer.
If f.Sensitive is true, "Never Indexed" representation is used. If
f.Sensitive is false and indexing is true, "Incremental Indexing"
representation is used.
appendTableSize appends v, as encoded in "Header Table Size Update"
representation, to dst and returns the extended buffer.
appendVarInt appends i, as encoded in variable integer form using n
bit prefix, to dst and returns the extended buffer.
See
https://httpwg.org/specs/rfc7541.html#integer.representation
encodeTypeByte returns type byte. If sensitive is true, type byte
for "Never Indexed" representation is returned. If sensitive is
false and indexing is true, type byte for "Incremental Indexing"
representation is returned. Otherwise, type byte for "Without
Indexing" is returned.
readVarInt reads an unsigned variable length integer off the
beginning of p. n is the parameter as described in
https://httpwg.org/specs/rfc7541.html#rfc.section.5.1.
n must always be between 1 and 8.
The returned remain buffer is either a smaller suffix of p, or err != nil.
The error is errNeedMore if p doesn't contain a complete integer.
Package-Level Variables (total 10, in which 2 are exported)
ErrInvalidHuffman is returned for errors found decoding
Huffman-encoded strings.
ErrStringLength is returned by Decoder.Write when the max string length
(as configured by Decoder.SetMaxStringLength) would be violated.
The pages are generated with Goldsv0.6.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.