changeset 7676:d225b70d38b6

Proxy: detection of data after final chunk. Previously, additional data after final chunk was either ignored (in the same buffer, or during unbuffered proxying) or sent to the client (in the next buffer already if it was already read from the socket). Now additional data are properly detected and ignored in all cases. Additionally, a warning is now logged and keepalive is disabled in the connection.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 06 Jul 2020 18:36:20 +0300
parents 9afa45068b8f
children a786e491d08d
files src/http/modules/ngx_http_proxy_module.c
diffstat 1 files changed, 30 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -2104,6 +2104,23 @@ ngx_http_proxy_chunked_filter(ngx_event_
         return NGX_ERROR;
     }
 
+    if (p->upstream_done) {
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
+                       "http proxy data after close");
+        return NGX_OK;
+    }
+
+    if (p->length == 0) {
+
+        ngx_log_error(NGX_LOG_WARN, p->log, 0,
+                      "upstream sent data after final chunk");
+
+        r->upstream->keepalive = 0;
+        p->upstream_done = 1;
+
+        return NGX_OK;
+    }
+
     b = NULL;
     prev = &buf->shadow;
 
@@ -2166,9 +2183,15 @@ ngx_http_proxy_chunked_filter(ngx_event_
 
             /* a whole response has been parsed successfully */
 
-            p->upstream_done = 1;
+            p->length = 0;
             r->upstream->keepalive = !r->upstream->headers_in.connection_close;
 
+            if (buf->pos != buf->last) {
+                ngx_log_error(NGX_LOG_WARN, p->log, 0,
+                              "upstream sent data after final chunk");
+                r->upstream->keepalive = 0;
+            }
+
             break;
         }
 
@@ -2347,6 +2370,12 @@ ngx_http_proxy_non_buffered_chunked_filt
             u->keepalive = !u->headers_in.connection_close;
             u->length = 0;
 
+            if (buf->pos != buf->last) {
+                ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+                              "upstream sent data after final chunk");
+                u->keepalive = 0;
+            }
+
             break;
         }