]> git.kaiwu.me - njs.git/commitdiff
HTTP: introduced detached subrequest mode in r.subrequest().
authorDmitry Volyntsev <xeioex@nginx.com>
Mon, 2 Mar 2020 18:11:37 +0000 (21:11 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Mon, 2 Mar 2020 18:11:37 +0000 (21:11 +0300)
If "options.detached" boolean flag is true the created subrequest is
a detached subrequest. Responses to detached subrequest are ignored.
Unlike ordinary subrequests, a detached subrequest can be created
inside a variable handler. The detached flag and callback argument are
mutually exclusive.

nginx/ngx_http_js_module.c

index 5771bd51eb62310d3feb4f4e96bc88b1890f97ce..5af7319fa93f06f28eb2a8dd4801fe7ab3b10cc1 100644 (file)
@@ -1786,7 +1786,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
 {
     ngx_int_t                 rc, promise;
     njs_str_t                 uri_arg, args_arg, method_name, body_arg;
-    ngx_uint_t                method, methods_max, has_body;
+    ngx_uint_t                method, methods_max, has_body, detached;
     njs_value_t              *value, *arg, *options;
     njs_function_t           *callback;
     ngx_http_js_ctx_t        *ctx;
@@ -1817,6 +1817,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     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");
+    static const njs_str_t detached_key = njs_str("detached");
 
     r = njs_vm_external(vm, njs_arg(args, nargs, 0));
     if (njs_slow_path(r == NULL)) {
@@ -1852,6 +1853,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     args_arg.start = NULL;
     has_body = 0;
     promise = 0;
+    detached = 0;
 
     arg = njs_arg(args, nargs, 2);
 
@@ -1881,6 +1883,11 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
             }
         }
 
+        value = njs_vm_object_prop(vm, options, &detached_key);
+        if (value != NULL) {
+            detached = njs_value_bool(value);
+        }
+
         value = njs_vm_object_prop(vm, options, &method_key);
         if (value != NULL) {
             if (ngx_http_js_string(vm, value, &method_name) != NJS_OK) {
@@ -1924,7 +1931,12 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
         }
     }
 
-    if (callback == NULL) {
+    if (detached && callback != NULL) {
+        njs_vm_error(vm, "detached flag and callback are mutually exclusive");
+        return NJS_ERROR;
+    }
+
+    if (!detached && callback == NULL) {
         callback = njs_vm_function_alloc(vm, ngx_http_js_promise_trampoline);
         if (callback == NULL) {
             goto memory_error;
@@ -1948,7 +1960,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
         sr->method_name.data = method_name.start;
     }
 
-    sr->header_only = (sr->method == NGX_HTTP_HEAD);
+    sr->header_only = (sr->method == NGX_HTTP_HEAD) || (callback == NULL);
 
     if (has_body) {
         rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
@@ -1993,6 +2005,8 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
                                      njs_value_arg(&ctx->promise_callbacks));
     }
 
+    njs_value_undefined_set(njs_vm_retval(vm));
+
     return NJS_OK;
 
 memory_error:
@@ -2015,22 +2029,30 @@ ngx_http_js_subrequest(ngx_http_request_t *r, njs_str_t *uri_arg,
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_js_module);
 
-    flags = NGX_HTTP_SUBREQUEST_BACKGROUND | NGX_HTTP_SUBREQUEST_IN_MEMORY;
+    flags = NGX_HTTP_SUBREQUEST_BACKGROUND;
 
-    ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
-    if (ps == NULL) {
-        njs_vm_error(ctx->vm, "internal error");
-        return NJS_ERROR;
-    }
+    if (callback != NULL) {
+        ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
+        if (ps == NULL) {
+            njs_vm_error(ctx->vm, "internal error");
+            return NJS_ERROR;
+        }
 
-    vm_event = njs_vm_add_event(ctx->vm, callback, 1, NULL, NULL);
-    if (vm_event == NULL) {
-        njs_vm_error(ctx->vm, "internal error");
-        return NJS_ERROR;
-    }
+        vm_event = njs_vm_add_event(ctx->vm, callback, 1, NULL, NULL);
+        if (vm_event == NULL) {
+            njs_vm_error(ctx->vm, "internal error");
+            return NJS_ERROR;
+        }
 
-    ps->handler = ngx_http_js_subrequest_done;
-    ps->data = vm_event;
+        ps->handler = ngx_http_js_subrequest_done;
+        ps->data = vm_event;
+
+        flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY;
+
+    } else {
+        ps = NULL;
+        vm_event = NULL;
+    }
 
     uri.len = uri_arg->length;
     uri.data = uri_arg->start;