changeset 8635:ef83990f0e25 quic

Fixed generating chunked response after 46e3542d51b3. If trailers were missing and a chain carrying the last_buf flag had no data in it, then last HTTP/1 chunk was broken. The problem was introduced while implementing HTTP/3 response body generation. The change fixes the issue and reduces diff to the mainline nginx.
author Roman Arutyunyan <arut@nginx.com>
date Tue, 10 Nov 2020 20:42:45 +0000
parents 831d1960826f
children ad7ca043edf5
files src/http/modules/ngx_http_chunked_filter_module.c
diffstat 1 files changed, 26 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/modules/ngx_http_chunked_filter_module.c
+++ b/src/http/modules/ngx_http_chunked_filter_module.c
@@ -18,7 +18,7 @@ typedef struct {
 
 static ngx_int_t ngx_http_chunked_filter_init(ngx_conf_t *cf);
 static ngx_chain_t *ngx_http_chunked_create_trailers(ngx_http_request_t *r,
-    ngx_http_chunked_filter_ctx_t *ctx, size_t size);
+    ngx_http_chunked_filter_ctx_t *ctx);
 
 
 static ngx_http_module_t  ngx_http_chunked_filter_module_ctx = {
@@ -204,8 +204,25 @@ ngx_http_chunked_body_filter(ngx_http_re
         out = tl;
     }
 
+#if (NGX_HTTP_V3)
+    if (r->http_version == NGX_HTTP_VERSION_30) {
+
+        if (cl->buf->last_buf) {
+            tl = ngx_http_v3_create_trailers(r);
+            if (tl == NULL) {
+                return NGX_ERROR;
+            }
+
+            cl->buf->last_buf = 0;
+
+            *ll = tl;
+        }
+
+    } else
+#endif
+
     if (cl->buf->last_buf) {
-        tl = ngx_http_chunked_create_trailers(r, ctx, size);
+        tl = ngx_http_chunked_create_trailers(r, ctx);
         if (tl == NULL) {
             return NGX_ERROR;
         }
@@ -214,12 +231,11 @@ ngx_http_chunked_body_filter(ngx_http_re
 
         *ll = tl;
 
-    } else if (size > 0
-#if (NGX_HTTP_V3)
-               && r->http_version != NGX_HTTP_VERSION_30
-#endif
-               )
-    {
+        if (size == 0) {
+            tl->buf->pos += 2;
+        }
+
+    } else if (size > 0) {
         tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
         if (tl == NULL) {
             return NGX_ERROR;
@@ -250,7 +266,7 @@ ngx_http_chunked_body_filter(ngx_http_re
 
 static ngx_chain_t *
 ngx_http_chunked_create_trailers(ngx_http_request_t *r,
-    ngx_http_chunked_filter_ctx_t *ctx, size_t size)
+    ngx_http_chunked_filter_ctx_t *ctx)
 {
     size_t            len;
     ngx_buf_t        *b;
@@ -259,12 +275,6 @@ ngx_http_chunked_create_trailers(ngx_htt
     ngx_list_part_t  *part;
     ngx_table_elt_t  *header;
 
-#if (NGX_HTTP_V3)
-    if (r->http_version == NGX_HTTP_VERSION_30) {
-        return ngx_http_v3_create_trailers(r);
-    }
-#endif
-
     len = 0;
 
     part = &r->headers_out.trailers.part;
@@ -317,10 +327,7 @@ ngx_http_chunked_create_trailers(ngx_htt
 
     b->last = b->pos;
 
-    if (size > 0) {
-        *b->last++ = CR; *b->last++ = LF;
-    }
-
+    *b->last++ = CR; *b->last++ = LF;
     *b->last++ = '0';
     *b->last++ = CR; *b->last++ = LF;