131 lines
5.9 KiB
ReStructuredText
131 lines
5.9 KiB
ReStructuredText
Tutorial: HPACK API
|
|
===================
|
|
|
|
In this tutorial, we describe basic use of HPACK API in nghttp2
|
|
library. We briefly describe APIs for deflating and inflating header
|
|
fields. The example of using these APIs are presented as complete
|
|
source code `deflate.c`_.
|
|
|
|
Deflating (encoding) headers
|
|
----------------------------
|
|
|
|
First we need to initialize :type:`nghttp2_hd_deflater` object using
|
|
`nghttp2_hd_deflate_new()` function::
|
|
|
|
int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
|
|
size_t deflate_hd_table_bufsize_max);
|
|
|
|
This function allocates :type:`nghttp2_hd_deflater` object and
|
|
initializes it and assigns its pointer to ``*deflater_ptr`` passed by
|
|
parameter. The *deflate_hd_table_bufsize_max* is the upper bound of
|
|
header table size the deflater will use. This will limit the memory
|
|
usage in deflater object for dynamic header table. If you doubt, just
|
|
specify 4096 here, which is the default upper bound of dynamic header
|
|
table buffer size.
|
|
|
|
To encode header fields, `nghttp2_hd_deflate_hd()` function::
|
|
|
|
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
|
uint8_t *buf, size_t buflen,
|
|
const nghttp2_nv *nva, size_t nvlen);
|
|
|
|
The *deflater* is the deflater object initialized by
|
|
`nghttp2_hd_deflate_new()` function described above. The *buf* is a
|
|
pointer to buffer to store encoded byte string. The *buflen* is
|
|
capacity of *buf*. The *nva* is a pointer to :type:`nghttp2_nv`,
|
|
which is an array of header fields to deflate. The *nvlen* is the
|
|
number of header fields which *nva* contains.
|
|
|
|
It is important to initialize and assign all members of
|
|
:type:`nghttp2_nv`. If a header field should not be inserted in
|
|
dynamic header table for a security reason, set
|
|
:macro:`NGHTTP2_NV_FLAG_NO_INDEX` flag in :member:`nghttp2_nv.flags`.
|
|
|
|
`nghttp2_hd_deflate_hd()` processes all headers given in *nva*. The
|
|
*nva* must include all request or response header fields to be sent in
|
|
one HEADERS (or optionally following (multiple) CONTINUATION
|
|
frame(s)). The *buf* must have enough space to store the encoded
|
|
result. Otherwise, the function will fail. To estimate the upper
|
|
bound of encoded result, use `nghttp2_hd_deflate_bound()` function::
|
|
|
|
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
|
|
const nghttp2_nv *nva, size_t nvlen);
|
|
|
|
Pass this function with the same paramters *deflater*, *nva* and
|
|
*nvlen* which will be passed to `nghttp2_hd_deflate_hd()`.
|
|
|
|
The subsequent call of `nghttp2_hd_deflate_hd()` will use current
|
|
encoder state and perform differential encoding which is the
|
|
fundamental compression gain for HPACK.
|
|
|
|
Once `nghttp2_hd_deflate_hd()` fails, it cannot be undone and its
|
|
further call with the same deflater object shall fail. So it is very
|
|
important to use `nghttp2_hd_deflate_bound()` to know the required
|
|
size of buffer.
|
|
|
|
To delete :type:`nghttp2_hd_deflater` object, use `nghttp2_hd_deflate_del()`
|
|
function.
|
|
|
|
.. note::
|
|
|
|
Generally, the order of header fields passed to
|
|
`nghttp2_hd_deflate_hd()` function is not preserved. It is known
|
|
that the relative ordering of header fields which do not share the
|
|
same name is insignificant. But some header fields sharing the
|
|
same name require the explicit ordering. To preserve this
|
|
ordering, those header values are concatenated into single header
|
|
field value using NULL (0x00) as delimiter. This is transparent to
|
|
HPACK API. Therefore, the application should examine the inflated
|
|
header values and split into multiple header field values by NULL.
|
|
|
|
Inflating (decoding) headers
|
|
----------------------------
|
|
|
|
We use :type:`nghttp2_hd_inflater` object to inflate compressed header
|
|
data. To initialize the object, use `nghttp2_hd_inflate_new()`::
|
|
|
|
int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr);
|
|
|
|
To inflate header data, use `nghttp2_hd_inflate_hd()` function::
|
|
|
|
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
|
|
nghttp2_nv *nv_out, int *inflate_flags,
|
|
uint8_t *in, size_t inlen, int in_final);
|
|
|
|
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
|
|
pointer to input data and *inlen* is its length. The caller is not
|
|
required to specify whole deflated header data to *in* at once. It
|
|
can call this function multiple times for portion of the data in
|
|
streaming way. If *in_final* is nonzero, it tells the function that
|
|
the passed data is the final sequence of deflated header data. The
|
|
*inflate_flags* is output parameter and successful call of this
|
|
function stores a set of flags in it. It will be described later.
|
|
|
|
This function returns when each header field is inflated. When this
|
|
happens, the function sets :macro:`NGHTTP2_HD_INFLATE_EMIT` flag to
|
|
*inflate_flag* parameter and header field is stored in *nv_out*. The
|
|
return value indicates the number of data read from *in* to processed
|
|
so far. It may be less than *inlen*. The caller should call the
|
|
function repeatedly until all data are processed by adjusting *in* and
|
|
*inlen* with the processed bytes.
|
|
|
|
If *in_final* is nonzero and all given data was processed, the
|
|
function sets :macro:`NGHTTP2_HD_INFLATE_FINAL` flag to
|
|
*inflate_flag*. If the caller sees this flag set, call
|
|
`nghttp2_hd_inflate_end_headers()` function.
|
|
|
|
If *in_final* is zero and :macro:`NGHTTP2_HD_INFLATE_EMIT` flag is not
|
|
set, it indicates that all given data was processed. The caller is
|
|
required to pass subsequent data.
|
|
|
|
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
|
|
differential encoding.
|
|
|
|
The example use of `nghttp2_hd_inflate_hd()` is shown in
|
|
`inflate_header_block()` function in `deflate.c`_.
|
|
|
|
To delete :type:`nghttp2_hd_inflater` object, use `nghttp2_hd_inflate_del()`
|
|
function.
|