From 63f5d46f58e537745987e9d68bc65b03830238a7 Mon Sep 17 00:00:00 2001 From: Piotr Sikora Date: Wed, 30 Aug 2017 14:52:11 -0700 Subject: [PATCH] HTTP/2: signal 0-byte HPACK's dynamic table size. This change lets NGINX talk to clients with SETTINGS_HEADER_TABLE_SIZE smaller than the default 4KB. Previously, NGINX would ACK the SETTINGS frame with a small dynamic table size, but it would never send dynamic table size update, leading to a connection-level COMPRESSION_ERROR. Also, it allows clients to release 4KB of memory per connection, since NGINX doesn't use HPACK's dynamic table when encoding headers, however clients had to maintain it, since NGINX never signaled that it doesn't use it. Signed-off-by: Piotr Sikora --- src/http/v2/ngx_http_v2.c | 2 ++ src/http/v2/ngx_http_v2.h | 1 + src/http/v2/ngx_http_v2_filter_module.c | 14 +++++++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 772561640..d99dd8342 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -245,6 +245,8 @@ ngx_http_v2_init(ngx_event_t *rev) h2c->frame_size = NGX_HTTP_V2_DEFAULT_FRAME_SIZE; + h2c->table_update = 1; + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h index 4804658eb..42e0eb132 100644 --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -144,6 +144,7 @@ struct ngx_http_v2_connection_s { unsigned closed_nodes:8; unsigned settings_ack:1; + unsigned table_update:1; unsigned blocked:1; unsigned goaway:1; }; diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c index 8621e7a4d..74aac6ef0 100644 --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -139,6 +139,7 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) ngx_connection_t *fc; ngx_http_cleanup_t *cln; ngx_http_v2_out_frame_t *frame; + ngx_http_v2_connection_t *h2c; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; u_char addr[NGX_SOCKADDR_STRLEN]; @@ -235,7 +236,11 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) } } - len = status ? 1 : 1 + ngx_http_v2_literal_size("418"); + h2c = r->stream->connection; + + len = h2c->table_update ? 1 : 0; + + len += status ? 1 : 1 + ngx_http_v2_literal_size("418"); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); @@ -423,6 +428,13 @@ ngx_http_v2_header_filter(ngx_http_request_t *r) start = pos; + if (h2c->table_update) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, + "http2 table size update: 0"); + *pos++ = (1 << 5) | 0; + h2c->table_update = 0; + } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 output header: \":status: %03ui\"", r->headers_out.status);