🙌
【C 言語】nghttp2 で HPACK 形式に圧縮された HTTP/2 ヘッダーを復元する
今度は HPACk 形式に圧縮された HTTP/2 ヘッダーを復元する。執筆時のテスト環境は Debian 12 Bookworm、nghttp2 1.52.0 である。
024年3月にリリースされた nghttp2 1.6.0 で ssize_t の問題を解決するために nghttp2_ssize に対応した新しい API が導入された。後方互換性のために古い API はエイリアスとなっている。
test.c
#include <stdio.h>
#include <string.h>
#include <nghttp2/nghttp2.h>
static int inflate_header_block(
nghttp2_hd_inflater *inflater,
uint8_t *in,
size_t inlen
);
int main(void) {
ssize_t rv;
nghttp2_hd_inflater *inflater;
uint8_t *buf = "\x87\x41\x88\x2f\x91\xd3\x5d\x05\x5c\xf6\x4d\x84\x7a\x87\xa0\xd1\xd5\x34\xe9\x4d\x62\x90";
size_t outlen = strlen(buf);
rv = nghttp2_hd_inflate_new(&inflater);
rv = inflate_header_block(inflater, buf, outlen);
nghttp2_hd_inflate_del(inflater);
return 0;
}
int inflate_header_block(
nghttp2_hd_inflater *inflater,
uint8_t *in,
size_t inlen) {
ssize_t rv;
for (;;) {
nghttp2_nv nv;
int inflate_flags = 0;
size_t proclen;
rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags, in, inlen, 1);
proclen = (size_t)rv;
in += proclen;
inlen -= proclen;
printf("proclen: %d inlen: %d\n", proclen, inlen);
if (inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
fwrite(nv.name, 1, nv.namelen, stderr);
fprintf(stderr, ": ");
fwrite(nv.value, 1, nv.valuelen, stderr);
fprintf(stderr, "\n");
}
if (inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
nghttp2_hd_inflate_end_headers(inflater);
break;
}
if ((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && inlen == 0) {
break;
}
}
return 0;
}
実行結果は次のとおり
zig run test.c -lc -lnghttp2
proclen: 1 inlen: 21
:scheme: https
proclen: 10 inlen: 11
:authority: example.org
proclen: 1 inlen: 10
:path: /
proclen: 9 inlen: 1
user-agent: libnghttp2
proclen: 1 inlen: 0
accept-encoding: gzip, deflate
proclen: 0 inlen: 0
Discussion