From: Dmitry Volyntsev Date: Thu, 5 Nov 2026 02:14:02 +0000 (-0800) Subject: Fetch: separate header storage from request and response records X-Git-Url: https://git.kaiwu.me/%7B@url%7D?a=commitdiff_plain;h=e59c5392c39e1a150f062b702e20b18dee419a88;p=njs.git Fetch: separate header storage from request and response records 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. --- diff --git a/nginx/ngx_js_fetch.c b/nginx/ngx_js_fetch.c index 73abe8ff..91ad5d5f 100644 --- a/nginx/ngx_js_fetch.c +++ b/nginx/ngx_js_fetch.c @@ -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; diff --git a/nginx/ngx_js_http.c b/nginx/ngx_js_http.c index e7b0e8a7..7fc02993 100644 --- a/nginx/ngx_js_http.c +++ b/nginx/ngx_js_http.c @@ -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++) { diff --git a/nginx/ngx_js_http.h b/nginx/ngx_js_http.h index 8bf06b4e..939c5ed4 100644 --- a/nginx/ngx_js_http.h +++ b/nginx/ngx_js_http.h @@ -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; diff --git a/nginx/ngx_qjs_fetch.c b/nginx/ngx_qjs_fetch.c index ff34dd55..d501be75 100644 --- a/nginx/ngx_qjs_fetch.c +++ b/nginx/ngx_qjs_fetch.c @@ -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; }