changeset 7913:185c86b830ef

Request body: introduced rb->last_saved flag. It indicates that the last buffer was received by the save filter, and can be used to check this at higher levels. To be used in the following changes.
author Maxim Dounin <mdounin@mdounin.ru>
date Sun, 29 Aug 2021 22:21:03 +0300
parents 96e09beaa2cf
children 9cf043a5d9ca
files src/http/ngx_http_request.h src/http/ngx_http_request_body.c
diffstat 2 files changed, 56 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/ngx_http_request.h	Sun Aug 29 22:20:54 2021 +0300
+++ b/src/http/ngx_http_request.h	Sun Aug 29 22:21:03 2021 +0300
@@ -302,6 +302,7 @@
     ngx_chain_t                      *busy;
     ngx_http_chunked_t               *chunked;
     ngx_http_client_body_handler_pt   post_handler;
+    unsigned                          last_saved:1;
 } ngx_http_request_body_t;
 
 
--- a/src/http/ngx_http_request_body.c	Sun Aug 29 22:20:54 2021 +0300
+++ b/src/http/ngx_http_request_body.c	Sun Aug 29 22:21:03 2021 +0300
@@ -69,6 +69,7 @@
      *     rb->busy = NULL;
      *     rb->chunked = NULL;
      *     rb->received = 0;
+     *     rb->last_saved = 0;
      */
 
     rb->rest = -1;
@@ -941,15 +942,32 @@
 
     rb = r->request_body;
 
+    out = NULL;
+    ll = &out;
+
     if (rb->rest == -1) {
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                        "http request body content length filter");
 
         rb->rest = r->headers_in.content_length_n;
-    }
+
+        if (rb->rest == 0) {
+
+            tl = ngx_chain_get_free_buf(r->pool, &rb->free);
+            if (tl == NULL) {
+                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            }
 
-    out = NULL;
-    ll = &out;
+            b = tl->buf;
+
+            ngx_memzero(b, sizeof(ngx_buf_t));
+
+            b->last_buf = 1;
+
+            *ll = tl;
+            ll = &tl->next;
+        }
+    }
 
     for (cl = in; cl; cl = cl->next) {
 
@@ -1013,6 +1031,9 @@
 
     rb = r->request_body;
 
+    out = NULL;
+    ll = &out;
+
     if (rb->rest == -1) {
 
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -1029,9 +1050,6 @@
         rb->rest = cscf->large_client_header_buffers.size;
     }
 
-    out = NULL;
-    ll = &out;
-
     for (cl = in; cl; cl = cl->next) {
 
         b = NULL;
@@ -1188,15 +1206,16 @@
 ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in)
 {
     ngx_buf_t                 *b;
-    ngx_chain_t               *cl;
+    ngx_chain_t               *cl, *tl, **ll;
     ngx_http_request_body_t   *rb;
 
     rb = r->request_body;
 
-#if (NGX_DEBUG)
+    ll = &rb->bufs;
+
+    for (cl = rb->bufs; cl; cl = cl->next) {
 
 #if 0
-    for (cl = rb->bufs; cl; cl = cl->next) {
         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
                        "http body old buf t:%d f:%d %p, pos %p, size: %z "
                        "file: %O, size: %O",
@@ -1205,10 +1224,13 @@
                        cl->buf->last - cl->buf->pos,
                        cl->buf->file_pos,
                        cl->buf->file_last - cl->buf->file_pos);
-    }
 #endif
 
+        ll = &cl->next;
+    }
+
     for (cl = in; cl; cl = cl->next) {
+
         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
                        "http body new buf t:%d f:%d %p, pos %p, size: %z "
                        "file: %O, size: %O",
@@ -1217,15 +1239,31 @@
                        cl->buf->last - cl->buf->pos,
                        cl->buf->file_pos,
                        cl->buf->file_last - cl->buf->file_pos);
+
+        if (cl->buf->last_buf) {
+
+            if (rb->last_saved) {
+                ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                              "duplicate last buf in save filter");
+                *ll = NULL;
+                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            }
+
+            rb->last_saved = 1;
+        }
+
+        tl = ngx_alloc_chain_link(r->pool);
+        if (tl == NULL) {
+            *ll = NULL;
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        tl->buf = cl->buf;
+        *ll = tl;
+        ll = &tl->next;
     }
 
-#endif
-
-    /* TODO: coalesce neighbouring buffers */
-
-    if (ngx_chain_add_copy(r->pool, &rb->bufs, in) != NGX_OK) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-    }
+    *ll = NULL;
 
     if (r->request_body_no_buffering) {
         return NGX_OK;