From 1f720e8298111d9fcc3b597b0b214568de4b541a Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Thu, 18 Jul 2024 18:01:57 -0700 Subject: [PATCH 1/5] Version bump. --- src/njs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/njs.h b/src/njs.h index 2e16ce4ee..8950a0db2 100644 --- a/src/njs.h +++ b/src/njs.h @@ -11,8 +11,8 @@ #include -#define NJS_VERSION "0.8.5" -#define NJS_VERSION_NUMBER 0x000805 +#define NJS_VERSION "0.8.6" +#define NJS_VERSION_NUMBER 0x000806 #include From 78342aab5c28bed5621dfbd87de6522ea57d5e5a Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Thu, 18 Jul 2024 16:24:04 -0700 Subject: [PATCH 2/5] Tests: ignoring subrequest execution order in js_subrequest.t. --- nginx/t/js_subrequests.t | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/nginx/t/js_subrequests.t b/nginx/t/js_subrequests.t index 4a58d6f3c..d38573ba6 100644 --- a/nginx/t/js_subrequests.t +++ b/nginx/t/js_subrequests.t @@ -280,7 +280,7 @@ $t->write_file('test.js', <write_file('test.js', <write_file('test.js', < {rep[p] = reply[p]}); replies.push(rep); if (replies.length == total) { + replies.sort((a, b) => a.uri < b.uri ? -1 : 1); reply.parent.return(200, JSON.stringify(replies)); } } @@ -546,9 +548,9 @@ is(get_json('/sr_js_in_subrequest'), '["JS-SUB"]', 'sr_js_in_subrequest'); is(get_json('/sr_unavail'), '[{"status":502,"uri":"/unavail"}]', 'sr_unavail'); is(get_json('/sr_out_of_order'), - '[{"status":404,"uri":"/unknown"},' . + '[{"status":200,"uri":"/p/delayed"},' . '{"status":206,"uri":"/p/sub1"},' . - '{"status":200,"uri":"/p/delayed"}]', + '{"status":404,"uri":"/unknown"}]', 'sr_multi'); is(get_json('/sr_pr'), '{"h":"xxx"}', 'sr_promise'); From e770aee56522f23c92f80bec3c19e69a23f0d639 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Wed, 17 Jul 2024 22:07:12 -0700 Subject: [PATCH 3/5] Tests: removed njs specific code from js_headers.t. --- nginx/t/js_headers.t | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nginx/t/js_headers.t b/nginx/t/js_headers.t index 787b5520f..2cb8c6609 100644 --- a/nginx/t/js_headers.t +++ b/nginx/t/js_headers.t @@ -388,12 +388,12 @@ $t->write_file('test.js', <write_file('test.js', < Date: Tue, 16 Jul 2024 22:02:06 -0700 Subject: [PATCH 4/5] HTTP: making ngx_http_js_header_t handler type generic. So it can be reused by QuickJS code. --- nginx/ngx_http_js_module.c | 130 +++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 62 deletions(-) diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index 0c8a3b119..f2dbffbcc 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -71,27 +71,20 @@ typedef struct { typedef struct { - ngx_http_request_t *request; - njs_opaque_value_t callbacks[2]; -} ngx_http_js_cb_t; - - -typedef struct { - njs_str_t name; -#if defined(nginx_version) && (nginx_version >= 1023000) + ngx_str_t name; unsigned flags; - njs_int_t (*handler)(njs_vm_t *vm, ngx_http_request_t *r, - unsigned flags, njs_str_t *name, - njs_value_t *setval, njs_value_t *retval); -#else - njs_int_t (*handler)(njs_vm_t *vm, ngx_http_request_t *r, - ngx_list_t *headers, njs_str_t *name, - njs_value_t *setval, njs_value_t *retval); - -#endif + uintptr_t handler; } ngx_http_js_header_t; +typedef njs_int_t (*njs_http_js_header_handler_t)(njs_vm_t *vm, + ngx_http_request_t *r, unsigned flags, njs_str_t *name, njs_value_t *setval, + njs_value_t *retval); +typedef njs_int_t (*njs_http_js_header_handler122_t)(njs_vm_t *vm, + ngx_http_request_t *r, ngx_list_t *headers, njs_str_t *name, + njs_value_t *setval, njs_value_t *retval); + + static ngx_int_t ngx_http_js_content_handler(ngx_http_request_t *r); static void ngx_http_js_content_event_handler(ngx_http_request_t *r); static void ngx_http_js_content_write_event_handler(ngx_http_request_t *r); @@ -1613,33 +1606,41 @@ ngx_http_js_ext_header_out(njs_vm_t *vm, njs_object_prop_t *prop, static ngx_http_js_header_t headers_out[] = { #if defined(nginx_version) && (nginx_version < 1023000) - { njs_str("Age"), ngx_http_js_header_single }, - { njs_str("Content-Type"), ngx_http_js_content_type122 }, - { njs_str("Content-Length"), ngx_http_js_content_length122 }, - { njs_str("Content-Encoding"), ngx_http_js_content_encoding122 }, - { njs_str("Date"), ngx_http_js_date122 }, - { njs_str("Etag"), ngx_http_js_header_single }, - { njs_str("Expires"), ngx_http_js_header_single }, - { njs_str("Last-Modified"), ngx_http_js_last_modified122 }, - { njs_str("Location"), ngx_http_js_location122 }, - { njs_str("Server"), ngx_http_js_server122 }, - { njs_str("Set-Cookie"), ngx_http_js_header_array }, - { njs_str("Retry-After"), ngx_http_js_header_single }, - { njs_str(""), ngx_http_js_header_generic }, + +#define header(name, h) { njs_str(name), 0, (uintptr_t) h } + header("Age", ngx_http_js_header_single), + header("Content-Type", ngx_http_js_content_type122), + header("Content-Length", ngx_http_js_content_length122), + header("Content-Encoding", ngx_http_js_content_encoding122), + header("Date", ngx_http_js_date122), + header("Etag", ngx_http_js_header_single), + header("Expires", ngx_http_js_header_single), + header("Last-Modified", ngx_http_js_last_modified122), + header("Location", ngx_http_js_location122), + header("Server", ngx_http_js_server122), + header("Set-Cookie", ngx_http_js_header_array), + header("Retry-After", ngx_http_js_header_single), + header("", ngx_http_js_header_generic), +#undef header + #else - { njs_str("Age"), NJS_HEADER_SINGLE, ngx_http_js_header_out }, - { njs_str("Content-Encoding"), 0, ngx_http_js_content_encoding }, - { njs_str("Content-Length"), 0, ngx_http_js_content_length }, - { njs_str("Content-Type"), 0, ngx_http_js_content_type }, - { njs_str("Date"), 0, ngx_http_js_date }, - { njs_str("Etag"), NJS_HEADER_SINGLE, ngx_http_js_header_out }, - { njs_str("Expires"), NJS_HEADER_SINGLE, ngx_http_js_header_out }, - { njs_str("Last-Modified"), 0, ngx_http_js_last_modified }, - { njs_str("Location"), 0, ngx_http_js_location }, - { njs_str("Server"), 0, ngx_http_js_server }, - { njs_str("Set-Cookie"), NJS_HEADER_ARRAY, ngx_http_js_header_out }, - { njs_str("Retry-After"), NJS_HEADER_SINGLE, ngx_http_js_header_out }, - { njs_str(""), 0, ngx_http_js_header_out }, + +#define header(name, fl, h) { njs_str(name), fl, (uintptr_t) h } + header("Age", NJS_HEADER_SINGLE, ngx_http_js_header_out), + header("Content-Encoding", 0, ngx_http_js_content_encoding), + header("Content-Length", 0, ngx_http_js_content_length), + header("Content-Type", 0, ngx_http_js_content_type), + header("Date", 0, ngx_http_js_date), + header("Etag", NJS_HEADER_SINGLE, ngx_http_js_header_out), + header("Expires", NJS_HEADER_SINGLE, ngx_http_js_header_out), + header("Last-Modified", 0, ngx_http_js_last_modified), + header("Location", 0, ngx_http_js_location), + header("Server", 0, ngx_http_js_server), + header("Set-Cookie", NJS_HEADER_ARRAY, ngx_http_js_header_out), + header("Retry-After", NJS_HEADER_SINGLE, ngx_http_js_header_out), + header("", 0, ngx_http_js_header_out), +#undef header + #endif }; @@ -1667,18 +1668,20 @@ ngx_http_js_ext_header_out(njs_vm_t *vm, njs_object_prop_t *prop, " headers were already sent", &name); } - for (h = headers_out; h->name.length > 0; h++) { - if (h->name.length == name.length - && ngx_strncasecmp(h->name.start, name.start, name.length) == 0) + for (h = headers_out; h->name.len > 0; h++) { + if (h->name.len == name.length + && ngx_strncasecmp(h->name.data, name.start, name.length) == 0) { break; } } #if defined(nginx_version) && (nginx_version < 1023000) - return h->handler(vm, r, &r->headers_out.headers, &name, setval, retval); + return ((njs_http_js_header_handler122_t) h->handler)(vm, r, + &r->headers_out.headers, &name, setval, retval); #else - return h->handler(vm, r, h->flags, &name, setval, retval); + return ((njs_http_js_header_handler_t) h->handler)(vm, r, h->flags, &name, + setval, retval); #endif } @@ -2746,18 +2749,20 @@ ngx_http_js_ext_header_in(njs_vm_t *vm, njs_object_prop_t *prop, ngx_http_js_header_t *h; static ngx_http_js_header_t headers_in[] = { - { njs_str("Content-Type"), ngx_http_js_header_single }, - { njs_str("Cookie"), ngx_http_js_header_cookie }, - { njs_str("ETag"), ngx_http_js_header_single }, - { njs_str("From"), ngx_http_js_header_single }, - { njs_str("Max-Forwards"), ngx_http_js_header_single }, - { njs_str("Referer"), ngx_http_js_header_single }, - { njs_str("Proxy-Authorization"), ngx_http_js_header_single }, - { njs_str("User-Agent"), ngx_http_js_header_single }, +#define header(name, h) { njs_str(name), 0, (uintptr_t) h } + header("Content-Type", ngx_http_js_header_single), + header("Cookie", ngx_http_js_header_cookie), + header("ETag", ngx_http_js_header_single), + header("From", ngx_http_js_header_single), + header("Max-Forwards", ngx_http_js_header_single), + header("Referer", ngx_http_js_header_single), + header("Proxy-Authorization", ngx_http_js_header_single), + header("User-Agent", ngx_http_js_header_single), #if (NGX_HTTP_X_FORWARDED_FOR) - { njs_str("X-Forwarded-For"), ngx_http_js_header_x_forwarded_for }, + header("X-Forwarded-For", ngx_http_js_header_x_forwarded_for), #endif - { njs_str(""), ngx_http_js_header_generic }, + header("", ngx_http_js_header_generic), +#undef header }; r = njs_vm_external(vm, ngx_http_js_request_proto_id, value); @@ -2778,15 +2783,16 @@ ngx_http_js_ext_header_in(njs_vm_t *vm, njs_object_prop_t *prop, return NJS_DECLINED; } - for (h = headers_in; h->name.length > 0; h++) { - if (h->name.length == name.length - && ngx_strncasecmp(h->name.start, name.start, name.length) == 0) + for (h = headers_in; h->name.len > 0; h++) { + if (h->name.len == name.length + && ngx_strncasecmp(h->name.data, name.start, name.length) == 0) { break; } } - return h->handler(vm, r, &r->headers_in.headers, &name, setval, retval); + return ((njs_http_js_header_handler122_t) h->handler)(vm, r, + &r->headers_in.headers, &name, setval, retval); } From a4c2482c9e575396726c967dc0baa0aed6633663 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Thu, 18 Jul 2024 17:55:20 -0700 Subject: [PATCH 5/5] HTTP: moving ngx_http_methods table out of subrequest() method. So it can be reused by QuickJS code. --- nginx/ngx_http_js_module.c | 57 +++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index f2dbffbcc..a38d32cf1 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -85,6 +85,12 @@ typedef njs_int_t (*njs_http_js_header_handler122_t)(njs_vm_t *vm, njs_value_t *setval, njs_value_t *retval); +typedef struct { + ngx_str_t name; + ngx_uint_t value; +} ngx_http_js_entry_t; + + static ngx_int_t ngx_http_js_content_handler(ngx_http_request_t *r); static void ngx_http_js_content_event_handler(ngx_http_request_t *r); static void ngx_http_js_content_write_event_handler(ngx_http_request_t *r); @@ -888,6 +894,25 @@ njs_module_t *njs_http_js_addon_modules[] = { }; +static ngx_http_js_entry_t ngx_http_methods[] = { + { ngx_string("GET"), NGX_HTTP_GET }, + { ngx_string("POST"), NGX_HTTP_POST }, + { ngx_string("HEAD"), NGX_HTTP_HEAD }, + { ngx_string("OPTIONS"), NGX_HTTP_OPTIONS }, + { ngx_string("PROPFIND"), NGX_HTTP_PROPFIND }, + { ngx_string("PUT"), NGX_HTTP_PUT }, + { ngx_string("MKCOL"), NGX_HTTP_MKCOL }, + { ngx_string("DELETE"), NGX_HTTP_DELETE }, + { ngx_string("COPY"), NGX_HTTP_COPY }, + { ngx_string("MOVE"), NGX_HTTP_MOVE }, + { ngx_string("PROPPATCH"), NGX_HTTP_PROPPATCH }, + { ngx_string("LOCK"), NGX_HTTP_LOCK }, + { ngx_string("UNLOCK"), NGX_HTTP_UNLOCK }, + { ngx_string("PATCH"), NGX_HTTP_PATCH }, + { ngx_string("TRACE"), NGX_HTTP_TRACE }, +}; + + static ngx_int_t ngx_http_js_content_handler(ngx_http_request_t *r) { @@ -3069,27 +3094,6 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, ngx_http_request_body_t *rb; ngx_http_post_subrequest_t *ps; - static const struct { - ngx_str_t name; - ngx_uint_t value; - } methods[] = { - { ngx_string("GET"), NGX_HTTP_GET }, - { ngx_string("POST"), NGX_HTTP_POST }, - { ngx_string("HEAD"), NGX_HTTP_HEAD }, - { ngx_string("OPTIONS"), NGX_HTTP_OPTIONS }, - { ngx_string("PROPFIND"), NGX_HTTP_PROPFIND }, - { ngx_string("PUT"), NGX_HTTP_PUT }, - { ngx_string("MKCOL"), NGX_HTTP_MKCOL }, - { ngx_string("DELETE"), NGX_HTTP_DELETE }, - { ngx_string("COPY"), NGX_HTTP_COPY }, - { ngx_string("MOVE"), NGX_HTTP_MOVE }, - { ngx_string("PROPPATCH"), NGX_HTTP_PROPPATCH }, - { ngx_string("LOCK"), NGX_HTTP_LOCK }, - { ngx_string("UNLOCK"), NGX_HTTP_UNLOCK }, - { ngx_string("PATCH"), NGX_HTTP_PATCH }, - { ngx_string("TRACE"), NGX_HTTP_TRACE }, - }; - static const njs_str_t args_key = njs_str("args"); static const njs_str_t method_key = njs_str("method"); static const njs_str_t body_key = njs_str("body"); @@ -3124,7 +3128,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, callback = NULL; method = 0; - methods_max = sizeof(methods) / sizeof(methods[0]); + methods_max = sizeof(ngx_http_methods) / sizeof(ngx_http_methods[0]); args_arg.length = 0; args_arg.start = NULL; @@ -3172,8 +3176,9 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } while (method < methods_max) { - if (method_name.length == methods[method].name.len - && ngx_memcmp(method_name.start, methods[method].name.data, + if (method_name.length == ngx_http_methods[method].name.len + && ngx_memcmp(method_name.start, + ngx_http_methods[method].name.data, method_name.length) == 0) { @@ -3283,8 +3288,8 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } if (method != methods_max) { - sr->method = methods[method].value; - sr->method_name = methods[method].name; + sr->method = ngx_http_methods[method].value; + sr->method_name = ngx_http_methods[method].name; } else { sr->method = NGX_HTTP_UNKNOWN;