[njs] Fetch: fixed setting of Content-Type header.

Dmitry Volyntsev xeioex at nginx.com
Thu Jun 22 22:41:21 UTC 2023


details:   https://hg.nginx.org/njs/rev/9537c55033d2
branches:  
changeset: 2164:9537c55033d2
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu Jun 22 15:40:36 2023 -0700
description:
Fetch: fixed setting of Content-Type header.

Previously, Content-Type was set unconditionally to
"text/plain;charset=UTF-8" when fetch request contained a string body.
This may overlap with user's Content-Type.

The fix is to set the header only if it was not set before.

This fixes #654 issue on Github.

diffstat:

 nginx/ngx_js_fetch.c       |  22 +++++++++++++++++++++-
 nginx/t/js_fetch_objects.t |  21 +++++++++++++++++++++
 2 files changed, 42 insertions(+), 1 deletions(-)

diffs (98 lines):

diff -r 6a9d7d28b12c -r 9537c55033d2 nginx/ngx_js_fetch.c
--- a/nginx/ngx_js_fetch.c	Thu Jun 22 15:37:16 2023 -0700
+++ b/nginx/ngx_js_fetch.c	Thu Jun 22 15:40:36 2023 -0700
@@ -65,6 +65,7 @@ typedef struct {
         GUARD_RESPONSE,
     }                              guard;
     ngx_list_t                     header_list;
+    ngx_js_tb_elt_t               *content_type;
 } ngx_js_headers_t;
 
 
@@ -1951,6 +1952,7 @@ ngx_js_request_constructor(njs_vm_t *vm,
      *  request->cache_mode = CACHE_MODE_DEFAULT;
      *  request->credentials = CREDENTIALS_SAME_ORIGIN;
      *  request->mode = MODE_NO_CORS;
+     *  request->headers.content_type = NULL;
      */
 
     ngx_memzero(request, sizeof(ngx_js_request_t));
@@ -2092,6 +2094,9 @@ ngx_js_request_constructor(njs_vm_t *vm,
              * just allocating a new one.
              */
 
+            ngx_memset(&request->headers, 0, sizeof(ngx_js_headers_t));
+            request->headers.guard = GUARD_REQUEST;
+
             rc = ngx_list_init(&request->headers.header_list, pool, 4,
                                sizeof(ngx_js_tb_elt_t));
             if (rc != NGX_OK) {
@@ -2112,7 +2117,9 @@ ngx_js_request_constructor(njs_vm_t *vm,
                 return NJS_ERROR;
             }
 
-            if (njs_value_is_string(value)) {
+            if (request->headers.content_type == NULL
+                && njs_value_is_string(value))
+            {
                 ret = ngx_js_headers_append(vm, &request->headers,
                                         (u_char *) "Content-Type",
                                         njs_length("Content-Type"),
@@ -2303,6 +2310,12 @@ ngx_js_headers_append(njs_vm_t *vm, ngx_
     h->value.len = vlen;
     h->next = NULL;
 
+    if (len == njs_strlen("Content-Type")
+        && ngx_strncasecmp(name, (u_char *) "Content-Type", len) == 0)
+    {
+        headers->content_type = h;
+    }
+
     return NJS_OK;
 }
 
@@ -3334,6 +3347,13 @@ ngx_headers_js_ext_delete(njs_vm_t *vm, 
         }
     }
 
+    if (name.length == njs_strlen("Content-Type")
+        && ngx_strncasecmp(name.start, (u_char *) "Content-Type", name.length)
+           == 0)
+    {
+        headers->content_type = NULL;
+    }
+
     njs_value_undefined_set(retval);
 
     return NJS_OK;
diff -r 6a9d7d28b12c -r 9537c55033d2 nginx/t/js_fetch_objects.t
--- a/nginx/t/js_fetch_objects.t	Thu Jun 22 15:37:16 2023 -0700
+++ b/nginx/t/js_fetch_objects.t	Thu Jun 22 15:40:36 2023 -0700
@@ -373,6 +373,27 @@ my $p0 = port(8080);
                 var body = await r.text();
                 return `\${body}: \${r.headers.get('Content-Type')}`;
              }, 'ABC: text/plain;charset=UTF-8'],
+            ['user content type', async () => {
+                var r = new Request("http://nginx.org",
+                                    {body: 'ABC',
+                                     headers: {'Content-Type': 'text/html'}});
+                return r.headers.get('Content-Type');
+             }, 'text/html'],
+            ['user content type from Headers()', async () => {
+                var h = new Headers();
+                h.append('Content-Type', 'text/html');
+                var r = new Request("http://nginx.org",
+                                    {body: 'ABC', headers: h});
+                return r.headers.get('Content-Type');
+             }, 'text/html'],
+            ['user content type deleted', async () => {
+                var h = new Headers();
+                h.append('Content-Type', 'text/html');
+                h.delete('Content-Type');
+                var r = new Request("http://nginx.org",
+                                    {body: 'ABC', headers: h});
+                return r.headers.get('Content-Type');
+             }, 'text/plain;charset=UTF-8'],
             ['GET body', () => {
                 try {
                     var r = new Request("http://nginx.org", {body: 'ABC'});


More information about the nginx-devel mailing list