Opened 6 years ago
Closed 6 years ago
#1538 closed defect (invalid)
gRPC upstreams cannot use dynamic HPACK
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | major | Milestone: | |
Component: | other | Version: | 1.13.x |
Keywords: | Cc: | ||
uname -a: | |||
nginx -V: | 1.13.10 |
Description
"upstream sent invalid http2 table index: 64 while reading response header from upstream,"
gRPC uses the HPACK header compression (https://tools.ietf.org/html/rfc7541), which allows for dynamic header compression by assigning each key/value pair an ID in an HPACK table. There is a static, pre-shared part of the HPACK table (values 0 .. 60), and a dynamic part. When a gRPC upstream uses a header for the first time, it sends "literal header with incremental indexing" (header name/value + id), and afterwards sends only the id ("indexed header").
nginx has the static HPACK values compiled in, but errors out on any attempt of the upstream to set a dynamic value (> 61). The client will only receive a 502. For example, any golang gRPC server is incompatible with nginx because the upstream will set content-type/application-grpc, which is not in the static HPACK table.
The offending code is https://github.com/nginx/nginx/blob/master/src/http/modules/ngx_http_grpc_module.c#L2626, which hardcodes the static table.
nginx explicitly announces that it does not support dynamic header compression by sending the SETTINGS_HEADER_TABLE_SIZE value set to 0, see here. Any attempt of an upstream server to use indexes from the dynamic range is a bug in the upstream server (note that at least grpc-go implementation is known to be buggy, see commit log in 2713b2dbf5bb).