]> git.kaiwu.me - njs.git/commitdiff
Fetch: separate header storage from request and response records
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 5 Nov 2026 02:14:02 +0000 (18:14 -0800)
committerDmitry Volyntsev <xeioexception@gmail.com>
Wed, 11 Nov 2026 21:33:45 +0000 (13:33 -0800)
Headers are embedded in Request and Response records, so a Headers view
cannot retain its storage independently of the parent record.

Use explicit header-storage pointers while keeping the existing pool
allocation and lifetime policy in both engines.  This prepares the
shared transport for independently owned QuickJS Headers without adding
allocator modes to the header helpers.

nginx/ngx_js_fetch.c
nginx/ngx_js_http.c
nginx/ngx_js_http.h
nginx/ngx_qjs_fetch.c

index 73abe8ff7a8cb9781ad3e88c2aa1b680609eadb3..91ad5d5fb7d91a4444101873a0fb7ca2c6fdad2d 100644 (file)
@@ -798,12 +798,19 @@ ngx_js_ext_response_constructor(njs_vm_t *vm, njs_value_t *args,
      *  request->status_text.length = 0;
      */
 
+    pool = ngx_external_pool(vm, njs_vm_external_ptr(vm));
+
     response->code = 200;
-    response->headers.guard = GUARD_RESPONSE;
+    response->headers = njs_mp_zalloc(njs_vm_memory_pool(vm),
+                                      sizeof(ngx_js_headers_t));
+    if (response->headers == NULL) {
+        njs_vm_memory_error(vm);
+        return NJS_ERROR;
+    }
 
-    pool = ngx_external_pool(vm, njs_vm_external_ptr(vm));
+    response->headers->guard = GUARD_RESPONSE;
 
-    rc = ngx_list_init(&response->headers.header_list, pool, 4,
+    rc = ngx_list_init(&response->headers->header_list, pool, 4,
                        sizeof(ngx_js_tb_elt_t));
     if (rc != NGX_OK) {
         njs_vm_memory_error(vm);
@@ -852,7 +859,7 @@ ngx_js_ext_response_constructor(njs_vm_t *vm, njs_value_t *args,
                 return NJS_ERROR;
             }
 
-            ret = ngx_js_headers_fill(vm, &response->headers, value);
+            ret = ngx_js_headers_fill(vm, response->headers, value);
             if (ret != NJS_OK) {
                 return NJS_ERROR;
             }
@@ -871,7 +878,7 @@ ngx_js_ext_response_constructor(njs_vm_t *vm, njs_value_t *args,
         njs_chb_append(&response->chain, bd.start, bd.length);
 
         if (njs_value_is_string(body)) {
-            ret = ngx_js_headers_append(vm, &response->headers,
+            ret = ngx_js_headers_append(vm, response->headers,
                                     (u_char *) "Content-Type",
                                     njs_length("Content-Type"),
                                     (u_char *) "text/plain;charset=UTF-8",
@@ -1332,11 +1339,18 @@ ngx_js_request_constructor(njs_vm_t *vm, ngx_js_request_t *request,
     request->method.len = 3;
     request->body.data = (u_char *) "";
     request->body.len = 0;
-    request->headers.guard = GUARD_REQUEST;
-
     pool = ngx_external_pool(vm, external);
 
-    rc = ngx_list_init(&request->headers.header_list, pool, 4,
+    request->headers = njs_mp_zalloc(njs_vm_memory_pool(vm),
+                                     sizeof(ngx_js_headers_t));
+    if (request->headers == NULL) {
+        njs_vm_memory_error(vm);
+        return NJS_ERROR;
+    }
+
+    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) {
         njs_vm_memory_error(vm);
@@ -1364,7 +1378,7 @@ ngx_js_request_constructor(njs_vm_t *vm, ngx_js_request_t *request,
         request->credentials = orig->credentials;
         request->mode = orig->mode;
 
-        ret = ngx_js_headers_inherit(vm, &request->headers, &orig->headers);
+        ret = ngx_js_headers_inherit(vm, request->headers, orig->headers);
         if (ret != NJS_OK) {
             return NJS_ERROR;
         }
@@ -1465,17 +1479,17 @@ ngx_js_request_constructor(njs_vm_t *vm, ngx_js_request_t *request,
              * just allocating a new one.
              */
 
-            ngx_memset(&request->headers, 0, sizeof(ngx_js_headers_t));
-            request->headers.guard = GUARD_REQUEST;
+            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,
+            rc = ngx_list_init(&request->headers->header_list, pool, 4,
                                sizeof(ngx_js_tb_elt_t));
             if (rc != NGX_OK) {
                 njs_vm_memory_error(vm);
                 return NJS_ERROR;
             }
 
-            ret = ngx_js_headers_fill(vm, &request->headers, headers);
+            ret = ngx_js_headers_fill(vm, request->headers, headers);
             if (ret != NJS_OK) {
                 return NJS_ERROR;
             }
@@ -1487,12 +1501,12 @@ ngx_js_request_constructor(njs_vm_t *vm, ngx_js_request_t *request,
                 return NJS_ERROR;
             }
 
-            if (!ngx_js_headers_has(&request->headers,
+            if (!ngx_js_headers_has(request->headers,
                                     (u_char *) "Content-Type",
                                     njs_length("Content-Type"))
                 && njs_value_is_string(value))
             {
-                ret = ngx_js_headers_append(vm, &request->headers,
+                ret = ngx_js_headers_append(vm, request->headers,
                                         (u_char *) "Content-Type",
                                         njs_length("Content-Type"),
                                         (u_char *) "text/plain;charset=UTF-8",
@@ -2142,7 +2156,7 @@ ngx_request_js_ext_headers(njs_vm_t *vm, njs_object_prop_t *prop,
     if (njs_value_is_null(njs_value_arg(&request->header_value))) {
         ret = njs_vm_external_create(vm, njs_value_arg(&request->header_value),
                                      ngx_http_js_fetch_headers_proto_id,
-                                     &request->headers, 0);
+                                     request->headers, 0);
         if (ret != NJS_OK) {
             njs_vm_memory_error(vm);
             return NJS_ERROR;
@@ -2269,7 +2283,7 @@ ngx_response_js_ext_headers(njs_vm_t *vm, njs_object_prop_t *prop,
     if (njs_value_is_null(njs_value_arg(&response->header_value))) {
         ret = njs_vm_external_create(vm, njs_value_arg(&response->header_value),
                                      ngx_http_js_fetch_headers_proto_id,
-                                     &response->headers, 0);
+                                     response->headers, 0);
         if (ret != NJS_OK) {
             njs_vm_memory_error(vm);
             return NJS_ERROR;
index e7b0e8a76e74326b54b4ac5606767362983283d9..7fc029938875bda1157466c410a105d127480e66 100644 (file)
@@ -848,8 +848,17 @@ ngx_js_http_process_headers(ngx_js_http_t *http)
 
     hp = &http->http_parse;
 
-    if (http->response.headers.header_list.size == 0) {
-        rc = ngx_list_init(&http->response.headers.header_list, http->pool, 4,
+    if (http->response.headers == NULL) {
+        http->response.headers = ngx_pcalloc(http->pool,
+                                             sizeof(ngx_js_headers_t));
+        if (http->response.headers == NULL) {
+            ngx_js_http_error(http, "alloc failed");
+            return NGX_ERROR;
+        }
+    }
+
+    if (http->response.headers->header_list.size == 0) {
+        rc = ngx_list_init(&http->response.headers->header_list, http->pool, 4,
                            sizeof(ngx_js_tb_elt_t));
         if (rc != NGX_OK) {
             ngx_js_http_error(http, "alloc failed");
@@ -864,7 +873,7 @@ ngx_js_http_process_headers(ngx_js_http_t *http)
             len = hp->header_name_end - hp->header_name_start;
             vlen = hp->header_end - hp->header_start;
 
-            rc = http->append_headers(http, &http->response.headers,
+            rc = http->append_headers(http, http->response.headers,
                                        hp->header_name_start, len,
                                        hp->header_start, vlen);
 
@@ -935,7 +944,7 @@ ngx_js_http_process_headers(ngx_js_http_t *http)
         }
 
         if (rc == NGX_DONE) {
-            http->response.headers.guard = GUARD_IMMUTABLE;
+            http->response.headers->guard = GUARD_IMMUTABLE;
             break;
         }
 
@@ -2413,7 +2422,7 @@ ngx_js_fetch_append_request_headers(njs_chb_t *chain,
     ngx_list_part_t  *part;
     ngx_js_tb_elt_t  *h;
 
-    part = &request->headers.header_list.part;
+    part = &request->headers->header_list.part;
     h = part->elts;
 
     for (i = 0; /* void */; i++) {
@@ -2498,7 +2507,7 @@ ngx_js_fetch_build_request(ngx_js_http_t *http, ngx_js_request_t *request,
 
     has_host = 0;
     has_user_agent = 0;
-    part = &request->headers.header_list.part;
+    part = &request->headers->header_list.part;
     h = part->elts;
 
     for (i = 0; /* void */; i++) {
index 8bf06b4e9f57423b725fe985cefa475eb62b9f61..939c5ed4f1b2f65e72a7f4db185029e9ba0c6efc 100644 (file)
@@ -101,7 +101,7 @@ typedef struct {
     u_char                         m[8];
     uint8_t                        body_used;
     ngx_str_t                      body;
-    ngx_js_headers_t               headers;
+    ngx_js_headers_t              *headers;
     njs_opaque_value_t             header_value;
 } ngx_js_request_t;
 
@@ -112,7 +112,7 @@ typedef struct {
     ngx_str_t                      status_text;
     uint8_t                        body_used;
     njs_chb_t                      chain;
-    ngx_js_headers_t               headers;
+    ngx_js_headers_t              *headers;
     njs_opaque_value_t             header_value;
 } ngx_js_response_t;
 
index ff34dd55a3a64c344c7542ed3d0aa800cc438660..d501be756c87d855e11e52137e6be71aea12ed64 100644 (file)
@@ -603,10 +603,17 @@ ngx_qjs_request_ctor(JSContext *cx, ngx_js_request_t *request,
     request->method.len = 3;
     request->body.data = NULL;
     request->body.len = 0;
-    request->headers.guard = GUARD_REQUEST;
     pool = ngx_qjs_external_pool(cx, JS_GetContextOpaque(cx));
 
-    rc = ngx_list_init(&request->headers.header_list, pool, 4,
+    request->headers = ngx_pcalloc(pool, sizeof(ngx_js_headers_t));
+    if (request->headers == NULL) {
+        JS_ThrowOutOfMemory(cx);
+        return NGX_ERROR;
+    }
+
+    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) {
         JS_ThrowOutOfMemory(cx);
@@ -641,7 +648,7 @@ ngx_qjs_request_ctor(JSContext *cx, ngx_js_request_t *request,
         request->credentials = orig->credentials;
         request->mode = orig->mode;
 
-        rc = ngx_qjs_headers_inherit(cx, &request->headers, &orig->headers);
+        rc = ngx_qjs_headers_inherit(cx, request->headers, orig->headers);
         if (rc != NGX_OK) {
             return NGX_ERROR;
         }
@@ -747,10 +754,10 @@ ngx_qjs_request_ctor(JSContext *cx, ngx_js_request_t *request,
              * just allocating a new one.
              */
 
-            ngx_memset(&request->headers, 0, sizeof(ngx_js_headers_t));
-            request->headers.guard = GUARD_REQUEST;
+            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,
+            rc = ngx_list_init(&request->headers->header_list, pool, 4,
                                sizeof(ngx_js_tb_elt_t));
             if (rc != NGX_OK) {
                 JS_FreeValue(cx, value);
@@ -758,7 +765,7 @@ ngx_qjs_request_ctor(JSContext *cx, ngx_js_request_t *request,
                 return NGX_ERROR;
             }
 
-            rc = ngx_qjs_headers_fill(cx, &request->headers, value);
+            rc = ngx_qjs_headers_fill(cx, request->headers, value);
             JS_FreeValue(cx, value);
 
             if (rc != NGX_OK) {
@@ -781,12 +788,12 @@ ngx_qjs_request_ctor(JSContext *cx, ngx_js_request_t *request,
                 return NGX_ERROR;
             }
 
-            if (!ngx_js_headers_has(&request->headers,
+            if (!ngx_js_headers_has(request->headers,
                                     (u_char *) "Content-Type",
                                     sizeof("Content-Type") - 1)
                 && JS_IsString(value))
             {
-                rc = ngx_qjs_headers_append(cx, &request->headers,
+                rc = ngx_qjs_headers_append(cx, request->headers,
                                         (u_char *) "Content-Type",
                                         sizeof("Content-Type") - 1,
                                         (u_char *) "text/plain;charset=UTF-8",
@@ -834,8 +841,13 @@ ngx_qjs_fetch_response_ctor(JSContext *cx, JSValueConst new_target, int argc,
      */
 
     response->code = 200;
-    response->headers.guard = GUARD_RESPONSE;
-    ret = ngx_list_init(&response->headers.header_list, pool, 4,
+    response->headers = ngx_pcalloc(pool, sizeof(ngx_js_headers_t));
+    if (response->headers == NULL) {
+        return JS_ThrowOutOfMemory(cx);
+    }
+
+    response->headers->guard = GUARD_RESPONSE;
+    ret = ngx_list_init(&response->headers->header_list, pool, 4,
                         sizeof(ngx_js_tb_elt_t));
     if (ret != NGX_OK) {
         return JS_ThrowOutOfMemory(cx);
@@ -905,7 +917,7 @@ ngx_qjs_fetch_response_ctor(JSContext *cx, JSValueConst new_target, int argc,
                 return JS_ThrowTypeError(cx, "Headers is not an object");
             }
 
-            rc = ngx_qjs_headers_fill(cx, &response->headers, value);
+            rc = ngx_qjs_headers_fill(cx, response->headers, value);
             JS_FreeValue(cx, value);
 
             if (rc != NGX_OK) {
@@ -955,7 +967,7 @@ string:
         }
 
         if (JS_IsString(body)) {
-            rc = ngx_qjs_headers_append(cx, &response->headers,
+            rc = ngx_qjs_headers_append(cx, response->headers,
                                       (u_char *) "Content-Type",
                                       sizeof("Content-Type") - 1,
                                       (u_char *) "text/plain;charset=UTF-8",
@@ -1388,7 +1400,7 @@ ngx_qjs_fetch_append_headers(ngx_js_http_t *http, ngx_js_headers_t *headers,
 
     fetch = (ngx_qjs_fetch_t *) http;
 
-    return ngx_qjs_headers_append(fetch->cx, &http->response.headers,
+    return ngx_qjs_headers_append(fetch->cx, http->response.headers,
                                   name, len, value, vlen);
 }
 
@@ -2118,7 +2130,7 @@ ngx_qjs_ext_fetch_request_headers(JSContext *cx, JSValueConst this_val)
             return JS_ThrowOutOfMemory(cx);
         }
 
-        JS_SetOpaque(header, &request->headers);
+        JS_SetOpaque(header, request->headers);
 
         object->header_value = header;
     }
@@ -2270,7 +2282,7 @@ ngx_qjs_ext_fetch_response_headers(JSContext *cx, JSValueConst this_val)
             return JS_ThrowOutOfMemory(cx);
         }
 
-        JS_SetOpaque(header, &response->headers);
+        JS_SetOpaque(header, response->headers);
 
         object->header_value = header;
     }