Tutorial: HPACK API =================== In this tutorial, we describe basic use of nghttp2's HPACK API. We briefly describe the APIs for deflating and inflating header fields. The full example of using these APIs, `deflate.c`_, is attached at the end of this page. It also resides in the examples directory in the archive or repository. Deflating (encoding) headers ---------------------------- First we need to initialize a :type:`nghttp2_hd_deflater` object using the `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 a :type:`nghttp2_hd_deflater` object, initializes it, and assigns its pointer to ``*deflater_ptr``. The *deflate_hd_table_bufsize_max* is the upper bound of header table size the deflater will use. This will limit the memory usage by the deflater object for the dynamic header table. If in doubt, just specify 4096 here, which is the default upper bound of dynamic header table buffer size. To encode header fields, use the `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()` described above. The encoded byte string is written to the buffer *buf*, which has length *buflen*. The *nva* is a pointer to an array of headers fields, each of type :type:`nghttp2_nv`. *nvlen* is the number of header fields which *nva* contains. It is important to initialize and assign all members of :type:`nghttp2_nv`. For security sensitive header fields (such as cookies), set the :macro:`NGHTTP2_NV_FLAG_NO_INDEX` flag in :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 *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 the encoded result length, use `nghttp2_hd_deflate_bound()`:: size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater, const nghttp2_nv *nva, size_t nvlen); Pass this function the same parameters (*deflater*, *nva*, and *nvlen*) which will be passed to `nghttp2_hd_deflate_hd()`. Subsequent calls to `nghttp2_hd_deflate_hd()` will use the current encoder state and perform differential encoding, which yields HPAC's fundamental compression gain. If `nghttp2_hd_deflate_hd()` fails, the failure is fatal and any further calls with the same deflater object will fail. Thus it's very important to use `nghttp2_hd_deflate_bound()` to determine the required size of the output buffer. To delete a :type:`nghttp2_hd_deflater` object, use the `nghttp2_hd_deflate_del()` function. Inflating (decoding) headers ---------------------------- A :type:`nghttp2_hd_inflater` object is used 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_hd2()`:: ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, int *inflate_flags, const uint8_t *in, size_t inlen, int in_final); `nghttp2_hd_inflate_hd2()` 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* is a pointer to a :type:`nghttp2_nv` into which one header field may be stored. The *in* is a pointer to input data, and *inlen* is its length. The caller is not required to specify the whole deflated header data via *in* at once: Instead it can call this function multiple times as additional data bytes become available. 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 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 happens, the function sets the :macro:`NGHTTP2_HD_INFLATE_EMIT` flag in *inflate_flags*, and a header field is stored in *nv_out*. The return value indicates the number of bytes read from *in* processed so far, which may be less than *inlen*. The caller should call the function repeatedly until all bytes are processed. 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 function sets the :macro:`NGHTTP2_HD_INFLATE_FINAL` flag in *inflate_flags*. When you see this flag set, call the `nghttp2_hd_inflate_end_headers()` function. If *in_final* is zero and the :macro:`NGHTTP2_HD_INFLATE_EMIT` flag is not set, it indicates that all given data was processed. The caller is required to pass additional data. Example usage of `nghttp2_hd_inflate_hd2()` is shown in the `inflate_header_block()` function in `deflate.c`_. Finally, to delete a :type:`nghttp2_hd_inflater` object, use `nghttp2_hd_inflate_del()`.