changeset 6515:8df664ebe037

HTTP/2: send WINDOW_UPDATE instead of RST_STREAM with NO_ERROR. After the 92464ebace8e change, it has been discovered that not all clients follow the RFC and handle RST_STREAM with NO_ERROR properly. Notably, Chrome currently interprets it as INTERNAL_ERROR and discards the response. As a workaround, instead of RST_STREAM the maximum stream window update will be sent, which will let client to send up to 2 GB of a request body data before getting stuck on flow control. All the received data will be silently discarded. See for details: http://mailman.nginx.org/pipermail/nginx-devel/2016-April/008143.html https://bugs.chromium.org/p/chromium/issues/detail?id=603182
author Valentin Bartenev <vbart@nginx.com>
date Thu, 14 Apr 2016 15:14:15 +0300
parents 0aa07850922f
children ab16126a06a0
files src/http/v2/ngx_http_v2.c
diffstat 1 files changed, 22 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/v2/ngx_http_v2.c
+++ b/src/http/v2/ngx_http_v2.c
@@ -3860,11 +3860,33 @@ ngx_http_v2_close_stream(ngx_http_v2_str
             }
 
         } else if (!stream->in_closed) {
+#if 0
             if (ngx_http_v2_send_rst_stream(h2c, node->id, NGX_HTTP_V2_NO_ERROR)
                 != NGX_OK)
             {
                 h2c->connection->error = 1;
             }
+#else
+            /*
+             * At the time of writing at least the latest versions of Chrome
+             * do not properly handle RST_STREAM with NO_ERROR status.
+             *
+             * See: https://bugs.chromium.org/p/chromium/issues/detail?id=603182
+             *
+             * As a workaround, the stream window is maximized before closing
+             * the stream.  This allows a client to send up to 2 GB of data
+             * before getting blocked on flow control.
+             */
+
+            if (stream->recv_window < NGX_HTTP_V2_MAX_WINDOW
+                && ngx_http_v2_send_window_update(h2c, node->id,
+                                                  NGX_HTTP_V2_MAX_WINDOW
+                                                  - stream->recv_window)
+                   != NGX_OK)
+            {
+                h2c->connection->error = 1;
+            }
+#endif
         }
     }