diff src/http/v2/ngx_http_v2_filter_module.c @ 7100:12cadc4669a7

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 <piotrsikora@google.com>
author Piotr Sikora <piotrsikora@google.com>
date Wed, 30 Aug 2017 14:52:11 -0700
parents 4e784e095a97
children 2bf605c6edf7
line wrap: on
line diff
--- 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_reque
     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_reque
         }
     }
 
-    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_reque
 
     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);