From 75d6b61a3800f77ba7ba75db445876d780ed1c18 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Mon, 5 Jan 2026 17:23:50 -0800 Subject: [PATCH] HTTP: improved r.subrequest() error handling after d34fcb0 (0.8.5). This reverts code changes introduced in d34fcb0. To fix the original problem JS errors are not propagated as nginx errors in r.subrequest(). This also fixes a problem of a lost write event when the njs handler making r.subrequest() is called from a lua handler as a subrequest: nginx.conf: ... location = /subrequest { access_by_lua_file scripts/subrequest.lua; proxy_pass http://localhost:8080/pass; } location = /nested/subrequest { internal; js_content main.getToken; } scripts/subrequest.lua: local res = ngx.location.capture('/nested/subrequest') ngx.log(ngx.STDERR, "Subrequest status: " .. res.status) if res.status ~= 200 then ngx.log(ngx.STDERR, "Subrequest failed with status: " .. res.status) return nil end return res.body main.js: async function getToken(r) { var reply = await r.subrequest('/api/auth'); r.error("reply.status :: " + reply.status); var status = reply.status; r.return(status, "{"result":"OK!"}"); } export default { getToken }; $ curl localhost:8080/subrequest error.log (before the fix): ... *1 http js event finalize rc: 0 *1 post event 0000B4BCA64C5FF0 *1 http log handler *1 http request count:3 blk:0 timer delta: 0 posted event 0000B4BCA64C5FF0 *1 delete posted event 0000B4BCA64C5FF0 *1 http run request: "/subrequest?" *1 access phase: 11 *1 lua access handler, uri:"/subrequest" c:2 *1 lua run write event handler: timedout:0, ready:1, writing_raw_req_socket:0 *1 useless lua write event handler <<<--- error.log (after the fix): ... *1 http js event finalize rc: 0 *1 http posted request: "/nested/subrequest?" *1 http js content write event handler *1 http js content rc: 0 *1 http finalize request: 0, "/nested/subrequest?" a:0, c:3 *1 lua run post subrequest handler, rc:0 c:3 *1 http log handler *1 http wake parent request: "/subrequest?" *1 http posted request: "/subrequest?" *1 access phase: 11 *1 lua access handler, uri:"/subrequest" c:2 *1 lua run subrequests done, resuming lua thread --- nginx/ngx_http_js_module.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index 63e55c80..6bc2bca3 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -365,8 +365,8 @@ static ngx_js_loc_conf_t *ngx_http_js_loc_conf(ngx_http_request_t *r); static ngx_js_ctx_t *ngx_http_js_ctx(ngx_http_request_t *r); static void ngx_http_js_periodic_handler(ngx_event_t *ev); +static void ngx_http_js_periodic_write_event_handler(ngx_http_request_t *r); static void ngx_http_js_periodic_shutdown_handler(ngx_event_t *ev); -static void ngx_http_js_periodic_write_handler(ngx_event_t *ev); static void ngx_http_js_periodic_finalize(ngx_http_request_t *r, ngx_int_t rc); static void ngx_http_js_periodic_destroy(ngx_http_request_t *r, ngx_js_periodic_t *periodic); @@ -3781,7 +3781,7 @@ ngx_http_js_subrequest_done(ngx_http_request_t *r, void *data, ngx_int_t rc) ngx_js_del_event(ctx, event); - ngx_http_js_event_finalize(r->parent, rc); + ngx_http_js_event_finalize(r->parent, NGX_OK); return NGX_OK; } @@ -4520,10 +4520,7 @@ ngx_http_js_periodic_handler(ngx_event_t *ev) c->data = r; c->destroyed = 0; c->pool = r->pool; - c->read->log = &periodic->log; c->read->handler = ngx_http_js_periodic_shutdown_handler; - c->write->log = &periodic->log; - c->write->handler = ngx_http_js_periodic_write_handler; periodic->connection = c; periodic->log_ctx.request = r; @@ -4537,6 +4534,7 @@ ngx_http_js_periodic_handler(ngx_event_t *ev) r->valid_unparsed_uri = 1; r->health_check = 1; + r->write_event_handler = ngx_http_js_periodic_write_event_handler; rc = ngx_http_js_init_vm(r, ngx_http_js_periodic_session_proto_id); @@ -4574,17 +4572,12 @@ ngx_http_js_periodic_handler(ngx_event_t *ev) static void -ngx_http_js_periodic_write_handler(ngx_event_t *ev) +ngx_http_js_periodic_write_event_handler(ngx_http_request_t *r) { - ngx_connection_t *c; - ngx_http_js_ctx_t *ctx; - ngx_http_request_t *r; - - c = ev->data; - r = c->data; + ngx_http_js_ctx_t *ctx; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http js periodic write handler"); + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http js periodic write event handler"); ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); @@ -4656,10 +4649,6 @@ ngx_http_js_periodic_destroy(ngx_http_request_t *r, ngx_js_periodic_t *periodic) c->fd = (ngx_socket_t) -1; c->pool = NULL; c->destroyed = 1; - - if (c->write->posted) { - ngx_delete_posted_event(c->write); - } } @@ -4738,8 +4727,10 @@ ngx_http_js_event_finalize(ngx_http_request_t *r, ngx_int_t rc) } if (rc == NGX_OK) { - ngx_post_event(r->connection->write, &ngx_posted_events); + ngx_http_post_request(r, NULL); } + + ngx_http_run_posted_requests(r->connection); } @@ -5882,7 +5873,7 @@ ngx_http_qjs_subrequest_done(ngx_http_request_t *r, void *data, ngx_int_t rc) JS_FreeValue(cx, reply); ngx_js_del_event(ctx, event); - ngx_http_js_event_finalize(r->parent, rc); + ngx_http_js_event_finalize(r->parent, NGX_OK); return NGX_OK; } -- 2.47.3