doc: Reword the HPAC tutorial.
The overall meaning is the same. I added a paragraph to introduce nghttp2_hd_inflate_hd(), and added an explanation of using NGHTTP2_NV_FLAG_NO_INDEX for security sensitive headers.
This commit is contained in:
parent
8410f684fb
commit
560955f50d
|
@ -1,118 +1,129 @@
|
||||||
Tutorial: HPACK API
|
Tutorial: HPACK API
|
||||||
===================
|
===================
|
||||||
|
|
||||||
In this tutorial, we describe basic use of HPACK API in nghttp2
|
In this tutorial, we describe basic use of nghttp2's HPACK API. We
|
||||||
library. We briefly describe APIs for deflating and inflating header
|
briefly describe the APIs for deflating and inflating header fields.
|
||||||
fields. The example of using these APIs are presented as complete
|
The full example of using these APIs, `deflate.c`_, is attached at the
|
||||||
source code `deflate.c`_.
|
end of this page. It also resides in the examples directory in the
|
||||||
|
archive or repository.
|
||||||
|
|
||||||
Deflating (encoding) headers
|
Deflating (encoding) headers
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
First we need to initialize :type:`nghttp2_hd_deflater` object using
|
First we need to initialize a :type:`nghttp2_hd_deflater` object using
|
||||||
`nghttp2_hd_deflate_new()` function::
|
the `nghttp2_hd_deflate_new()` function::
|
||||||
|
|
||||||
int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
|
int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
|
||||||
size_t deflate_hd_table_bufsize_max);
|
size_t deflate_hd_table_bufsize_max);
|
||||||
|
|
||||||
This function allocates :type:`nghttp2_hd_deflater` object and
|
This function allocates a :type:`nghttp2_hd_deflater` object,
|
||||||
initializes it and assigns its pointer to ``*deflater_ptr`` passed by
|
initializes it, and assigns its pointer to ``*deflater_ptr``. The
|
||||||
parameter. The *deflate_hd_table_bufsize_max* is the upper bound of
|
*deflate_hd_table_bufsize_max* is the upper bound of header table size
|
||||||
header table size the deflater will use. This will limit the memory
|
the deflater will use. This will limit the memory usage by the
|
||||||
usage in deflater object for dynamic header table. If you doubt, just
|
deflater object for the dynamic header table. If in doubt, just
|
||||||
specify 4096 here, which is the default upper bound of dynamic header
|
specify 4096 here, which is the default upper bound of dynamic header
|
||||||
table buffer size.
|
table buffer size.
|
||||||
|
|
||||||
To encode header fields, `nghttp2_hd_deflate_hd()` function::
|
To encode header fields, use the `nghttp2_hd_deflate_hd()` function::
|
||||||
|
|
||||||
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
||||||
uint8_t *buf, size_t buflen,
|
uint8_t *buf, size_t buflen,
|
||||||
const nghttp2_nv *nva, size_t nvlen);
|
const nghttp2_nv *nva, size_t nvlen);
|
||||||
|
|
||||||
The *deflater* is the deflater object initialized by
|
The *deflater* is the deflater object initialized by
|
||||||
`nghttp2_hd_deflate_new()` function described above. The *buf* is a
|
`nghttp2_hd_deflate_new()` described above. The encoded byte string is
|
||||||
pointer to buffer to store encoded byte string. The *buflen* is
|
written to the buffer *buf*, which has length *buflen*. The *nva* is
|
||||||
capacity of *buf*. The *nva* is a pointer to :type:`nghttp2_nv`,
|
a pointer to an array of headers fields, each of type
|
||||||
which is an array of header fields to deflate. The *nvlen* is the
|
:type:`nghttp2_nv`. *nvlen* is the number of header fields which
|
||||||
number of header fields which *nva* contains.
|
*nva* contains.
|
||||||
|
|
||||||
It is important to initialize and assign all members of
|
It is important to initialize and assign all members of
|
||||||
:type:`nghttp2_nv`. If a header field should not be inserted in
|
:type:`nghttp2_nv`. For security sensitive header fields (such as
|
||||||
dynamic header table for a security reason, set
|
cookies), set the :macro:`NGHTTP2_NV_FLAG_NO_INDEX` flag in
|
||||||
:macro:`NGHTTP2_NV_FLAG_NO_INDEX` flag in :member:`nghttp2_nv.flags`.
|
:member:`nghttp2_nv.flags`. Setting this flag prevents recovery of
|
||||||
|
sensitive header fields by compression based attacks: This is achieved
|
||||||
|
by not inserting the header field into the dynamic header table.
|
||||||
|
|
||||||
`nghttp2_hd_deflate_hd()` processes all headers given in *nva*. The
|
`nghttp2_hd_deflate_hd()` processes all headers given in *nva*. The
|
||||||
*nva* must include all request or response header fields to be sent in
|
*nva* must include all request or response header fields to be sent in
|
||||||
one HEADERS (or optionally following (multiple) CONTINUATION
|
one HEADERS (or optionally following (multiple) CONTINUATION
|
||||||
frame(s)). The *buf* must have enough space to store the encoded
|
frame(s)). The *buf* must have enough space to store the encoded
|
||||||
result. Otherwise, the function will fail. To estimate the upper
|
result, otherwise the function will fail. To estimate the upper bound
|
||||||
bound of encoded result, use `nghttp2_hd_deflate_bound()` function::
|
of the encoded result length, use `nghttp2_hd_deflate_bound()`::
|
||||||
|
|
||||||
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
|
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
|
||||||
const nghttp2_nv *nva, size_t nvlen);
|
const nghttp2_nv *nva, size_t nvlen);
|
||||||
|
|
||||||
Pass this function with the same parameters *deflater*, *nva* and
|
Pass this function the same parameters (*deflater*, *nva*, and
|
||||||
*nvlen* which will be passed to `nghttp2_hd_deflate_hd()`.
|
*nvlen*) which will be passed to `nghttp2_hd_deflate_hd()`.
|
||||||
|
|
||||||
The subsequent call of `nghttp2_hd_deflate_hd()` will use current
|
Subsequent calls to `nghttp2_hd_deflate_hd()` will use the current
|
||||||
encoder state and perform differential encoding which is the
|
encoder state and perform differential encoding, which yields HPAC's
|
||||||
fundamental compression gain for HPACK.
|
fundamental compression gain.
|
||||||
|
|
||||||
Once `nghttp2_hd_deflate_hd()` fails, it cannot be undone and its
|
If `nghttp2_hd_deflate_hd()` fails, the failure is fatal and any
|
||||||
further call with the same deflater object shall fail. So it is very
|
further calls with the same deflater object will fail. Thus it's very
|
||||||
important to use `nghttp2_hd_deflate_bound()` to know the required
|
important to use `nghttp2_hd_deflate_bound()` to determine the
|
||||||
size of buffer.
|
required size of the output buffer.
|
||||||
|
|
||||||
To delete :type:`nghttp2_hd_deflater` object, use `nghttp2_hd_deflate_del()`
|
To delete a :type:`nghttp2_hd_deflater` object, use the
|
||||||
function.
|
`nghttp2_hd_deflate_del()` function.
|
||||||
|
|
||||||
Inflating (decoding) headers
|
Inflating (decoding) headers
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
We use :type:`nghttp2_hd_inflater` object to inflate compressed header
|
A :type:`nghttp2_hd_inflater` object is used to inflate compressed
|
||||||
data. To initialize the object, use `nghttp2_hd_inflate_new()`::
|
header data. To initialize the object, use
|
||||||
|
`nghttp2_hd_inflate_new()`::
|
||||||
|
|
||||||
int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr);
|
int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr);
|
||||||
|
|
||||||
To inflate header data, use `nghttp2_hd_inflate_hd()` function::
|
To inflate header data, use `nghttp2_hd_inflate_hd()`::
|
||||||
|
|
||||||
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
|
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
|
||||||
nghttp2_nv *nv_out, int *inflate_flags,
|
nghttp2_nv *nv_out, int *inflate_flags,
|
||||||
uint8_t *in, size_t inlen, int in_final);
|
uint8_t *in, size_t inlen, int in_final);
|
||||||
|
|
||||||
|
`nghttp2_hd_inflate_hd()` reads a stream of bytes and outputs a single
|
||||||
|
header field at a time. Multiple calls are normally required to read a
|
||||||
|
full stream of bytes and output all of the header fields.
|
||||||
|
|
||||||
The *inflater* is the inflater object initialized above. The *nv_out*
|
The *inflater* is the inflater object initialized above. The *nv_out*
|
||||||
is a pointer to :type:`nghttp2_nv` to store the result. The *in* is a
|
is a pointer to a :type:`nghttp2_nv` into which one header field may
|
||||||
pointer to input data and *inlen* is its length. The caller is not
|
be stored. The *in* is a pointer to input data, and *inlen* is its
|
||||||
required to specify whole deflated header data to *in* at once. It
|
length. The caller is not required to specify the whole deflated
|
||||||
can call this function multiple times for portion of the data in
|
header data via *in* at once: Instead it can call this function
|
||||||
streaming way. If *in_final* is nonzero, it tells the function that
|
multiple times as additional data bytes become available. If
|
||||||
the passed data is the final sequence of deflated header data. The
|
*in_final* is nonzero, it tells the function that the passed data is
|
||||||
*inflate_flags* is output parameter and successful call of this
|
the final sequence of deflated header data.
|
||||||
function stores a set of flags in it. It will be described later.
|
|
||||||
|
The *inflate_flags* is an output parameter; on success the function
|
||||||
|
sets it to a bitset of flags. It will be described later.
|
||||||
|
|
||||||
This function returns when each header field is inflated. When this
|
This function returns when each header field is inflated. When this
|
||||||
happens, the function sets :macro:`NGHTTP2_HD_INFLATE_EMIT` flag to
|
happens, the function sets the :macro:`NGHTTP2_HD_INFLATE_EMIT` flag
|
||||||
*inflate_flag* parameter and header field is stored in *nv_out*. The
|
in *inflate_flags*, and a header field is stored in *nv_out*. The
|
||||||
return value indicates the number of data read from *in* to processed
|
return value indicates the number of bytes read from *in* processed so
|
||||||
so far. It may be less than *inlen*. The caller should call the
|
far, which may be less than *inlen*. The caller should call the
|
||||||
function repeatedly until all data are processed by adjusting *in* and
|
function repeatedly until all bytes are processed. Processed bytes
|
||||||
*inlen* with the processed bytes.
|
should be removed from *in*, and *inlen* should be adjusted
|
||||||
|
appropriately.
|
||||||
|
|
||||||
If *in_final* is nonzero and all given data was processed, the
|
If *in_final* is nonzero and all given data was processed, the
|
||||||
function sets :macro:`NGHTTP2_HD_INFLATE_FINAL` flag to
|
function sets the :macro:`NGHTTP2_HD_INFLATE_FINAL` flag in
|
||||||
*inflate_flag*. If the caller sees this flag set, call
|
*inflate_flags*. When you see this flag set, call the
|
||||||
`nghttp2_hd_inflate_end_headers()` function.
|
`nghttp2_hd_inflate_end_headers()` function.
|
||||||
|
|
||||||
If *in_final* is zero and :macro:`NGHTTP2_HD_INFLATE_EMIT` flag is not
|
If *in_final* is zero and the :macro:`NGHTTP2_HD_INFLATE_EMIT` flag is
|
||||||
set, it indicates that all given data was processed. The caller is
|
not set, it indicates that all given data was processed. The caller
|
||||||
required to pass subsequent data.
|
is required to pass additional data.
|
||||||
|
|
||||||
It is important to note that the function may produce one or more
|
It is important to note that the function may produce one or more
|
||||||
header fields even if *inlen* is 0 when *in_final* is nonzero, due to
|
header fields even if *inlen* is 0 when *in_final* is nonzero, due to
|
||||||
differential encoding.
|
differential encoding.
|
||||||
|
|
||||||
The example use of `nghttp2_hd_inflate_hd()` is shown in
|
Example usage of `nghttp2_hd_inflate_hd()` is shown in the
|
||||||
`inflate_header_block()` function in `deflate.c`_.
|
`inflate_header_block()` function in `deflate.c`_.
|
||||||
|
|
||||||
To delete :type:`nghttp2_hd_inflater` object, use `nghttp2_hd_inflate_del()`
|
Finally, to delete a :type:`nghttp2_hd_inflater` object, use
|
||||||
function.
|
`nghttp2_hd_inflate_del()`.
|
||||||
|
|
Loading…
Reference in New Issue