]> git.kaiwu.me - njs.git/commitdiff
HTTP: improved r.subrequest() error handling after d34fcb0 (0.8.5).
authorDmitry Volyntsev <xeioex@nginx.com>
Tue, 6 Jan 2026 01:23:50 +0000 (17:23 -0800)
committerDmitry Volyntsev <xeioexception@gmail.com>
Wed, 7 Jan 2026 23:22:29 +0000 (15:22 -0800)
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

index 63e55c8003082743923788543e753955d1f1474c..6bc2bca3a3360320cd14c34e21f90788cf541c9e 100644 (file)
@@ -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;
 }