[njs] Modules: fixed reading response body in fetch API.

Dmitry Volyntsev xeioex at nginx.com
Thu Jul 21 02:58:37 UTC 2022


details:   https://hg.nginx.org/njs/rev/c597ee3450ab
branches:  
changeset: 1915:c597ee3450ab
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Wed Jul 20 17:49:00 2022 -0700
description:
Modules: fixed reading response body in fetch API.

Previously, the response body was ignored if the Content-Length was
missing.

This closes #557 issue on Github.

diffstat:

 nginx/ngx_js_fetch.c |  49 ++++++++++++++++++++++++++++++++-----------------
 1 files changed, 32 insertions(+), 17 deletions(-)

diffs (90 lines):

diff -r d7a0a16d22e4 -r c597ee3450ab nginx/ngx_js_fetch.c
--- a/nginx/ngx_js_fetch.c	Wed Jul 20 19:56:42 2022 -0700
+++ b/nginx/ngx_js_fetch.c	Wed Jul 20 17:49:00 2022 -0700
@@ -623,6 +623,8 @@ ngx_js_http_alloc(njs_vm_t *vm, ngx_pool
 
     http->timeout = 10000;
 
+    http->http_parse.content_length_n = -1;
+
     ret = njs_vm_promise_create(vm, njs_value_arg(&http->promise),
                                 njs_value_arg(&http->promise_callbacks));
     if (ret != NJS_OK) {
@@ -1388,7 +1390,7 @@ ngx_js_http_process_headers(ngx_js_http_
 static ngx_int_t
 ngx_js_http_process_body(ngx_js_http_t *http)
 {
-    ssize_t     size, need;
+    ssize_t     size, chsize, need;
     ngx_int_t   rc;
     njs_int_t   ret;
     ngx_buf_t  *b;
@@ -1403,7 +1405,16 @@ ngx_js_http_process_body(ngx_js_http_t *
             return NGX_ERROR;
         }
 
-        if (size == http->http_parse.content_length_n) {
+        if (http->http_parse.chunked
+            && http->http_parse.content_length_n == -1)
+        {
+            ngx_js_http_error(http, 0, "invalid fetch chunked response");
+            return NGX_ERROR;
+        }
+
+        if (http->http_parse.content_length_n == -1
+            || size == http->http_parse.content_length_n)
+        {
             ret = njs_vm_external_create(http->vm, njs_value_arg(&http->reply),
                                          ngx_http_js_fetch_proto_id, http, 0);
             if (ret != NJS_OK) {
@@ -1415,13 +1426,6 @@ ngx_js_http_process_body(ngx_js_http_t *
             return NGX_DONE;
         }
 
-        if (http->http_parse.chunked
-            && http->http_parse.content_length_n == 0)
-        {
-            ngx_js_http_error(http, 0, "invalid fetch chunked response");
-            return NGX_ERROR;
-        }
-
         if (size < http->http_parse.content_length_n) {
             return NGX_AGAIN;
         }
@@ -1454,17 +1458,28 @@ ngx_js_http_process_body(ngx_js_http_t *
         b->pos = http->http_chunk_parse.pos;
 
     } else {
-        need = http->http_parse.content_length_n - njs_chb_size(&http->chain);
-        size = ngx_min(need, b->last - b->pos);
-
-        if (size > 0) {
-            njs_chb_append(&http->chain, b->pos, size);
-            b->pos += size;
-            rc = NGX_AGAIN;
+        size = njs_chb_size(&http->chain);
+
+        if (http->http_parse.content_length_n == -1) {
+            need = http->max_response_body_size - size;
 
         } else {
-            rc = NGX_DONE;
+            need = http->http_parse.content_length_n - size;
         }
+
+        chsize = ngx_min(need, b->last - b->pos);
+
+        if (size + chsize > http->max_response_body_size) {
+            ngx_js_http_error(http, 0, "fetch response body is too large");
+            return NGX_ERROR;
+        }
+
+        if (chsize > 0) {
+            njs_chb_append(&http->chain, b->pos, chsize);
+            b->pos += chsize;
+        }
+
+        rc = (need > chsize) ? NGX_AGAIN : NGX_DONE;
     }
 
     if (b->pos == b->end) {



More information about the nginx-devel mailing list