[njs] HTTP: introduced promise support in r.subrequest().
Dmitry Volyntsev
xeioex at nginx.com
Thu Jan 16 16:35:02 UTC 2020
details: https://hg.nginx.org/njs/rev/6fccbc9f1288
branches:
changeset: 1301:6fccbc9f1288
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Thu Jan 16 19:18:39 2020 +0300
description:
HTTP: introduced promise support in r.subrequest().
If callback is not provided r.subrequest() returns an ordinary
Promise object that resolves to subrequest response object.
diffstat:
nginx/ngx_http_js_module.c | 86 ++++++++++++++++++++++++++++++++-------------
src/njs.h | 10 +++++
src/njs_function.c | 18 +++++++++
src/njs_promise.c | 22 +++++++++++
src/njs_value.h | 2 -
5 files changed, 111 insertions(+), 27 deletions(-)
diffs (254 lines):
diff -r cb4f1052954f -r 6fccbc9f1288 nginx/ngx_http_js_module.c
--- a/nginx/ngx_http_js_module.c Thu Jan 16 15:14:38 2020 +0300
+++ b/nginx/ngx_http_js_module.c Thu Jan 16 19:18:39 2020 +0300
@@ -32,6 +32,7 @@ typedef struct {
njs_opaque_value_t request;
njs_opaque_value_t request_body;
ngx_str_t redirect_uri;
+ njs_opaque_value_t promise_callbacks[2];
} ngx_http_js_ctx_t;
@@ -1760,10 +1761,30 @@ ngx_http_js_ext_set_variable(njs_vm_t *v
static njs_int_t
+ngx_http_js_promise_trampoline(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t unused)
+{
+ njs_function_t *callback;
+ ngx_http_js_ctx_t *ctx;
+ ngx_http_request_t *r;
+
+ r = njs_vm_external(vm, njs_argument(args, 1));
+ ctx = ngx_http_get_module_ctx(r, ngx_http_js_module);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "js subrequest promise trampoline ctx: %p", ctx);
+
+ callback = njs_value_function(njs_value_arg(&ctx->promise_callbacks[0]));
+
+ return njs_vm_call(vm, callback, njs_argument(args, 1), 1);
+}
+
+
+static njs_int_t
ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- ngx_int_t rc;
+ ngx_int_t rc, promise;
njs_str_t uri_arg, args_arg, method_name, body_arg;
ngx_uint_t method, methods_max, has_body;
njs_value_t *value, *arg, *options;
@@ -1799,6 +1820,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm,
r = njs_vm_external(vm, njs_arg(args, nargs, 0));
if (njs_slow_path(r == NULL)) {
+ njs_vm_error(vm, "this is not an external");
return NJS_ERROR;
}
@@ -1829,6 +1851,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm,
args_arg.length = 0;
args_arg.start = NULL;
has_body = 0;
+ promise = 0;
arg = njs_arg(args, nargs, 2);
@@ -1901,6 +1924,15 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm,
}
}
+ if (callback == NULL) {
+ callback = njs_vm_function_alloc(vm, ngx_http_js_promise_trampoline);
+ if (callback == NULL) {
+ goto memory_error;
+ }
+
+ promise = 1;
+ }
+
rc = ngx_http_js_subrequest(r, &uri_arg, &args_arg, callback, &sr);
if (rc != NGX_OK) {
return NJS_ERROR;
@@ -1916,7 +1948,7 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm,
sr->method_name.data = method_name.start;
}
- sr->header_only = (sr->method == NGX_HTTP_HEAD) || (callback == NULL);
+ sr->header_only = (sr->method == NGX_HTTP_HEAD);
if (has_body) {
rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
@@ -1949,6 +1981,18 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm,
sr->headers_in.chunked = 0;
}
+ if (promise) {
+ ctx = ngx_pcalloc(sr->pool, sizeof(ngx_http_js_ctx_t));
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_http_set_ctx(sr, ctx, ngx_http_js_module);
+
+ return njs_vm_promise_create(vm, njs_vm_retval(vm),
+ njs_value_arg(&ctx->promise_callbacks));
+ }
+
return NJS_OK;
memory_error:
@@ -1971,31 +2015,23 @@ ngx_http_js_subrequest(ngx_http_request_
ctx = ngx_http_get_module_ctx(r, ngx_http_js_module);
- flags = NGX_HTTP_SUBREQUEST_BACKGROUND;
-
- 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;
- }
-
- ps->handler = ngx_http_js_subrequest_done;
- ps->data = vm_event;
-
- flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY;
-
- } else {
- ps = NULL;
- vm_event = NULL;
+ flags = NGX_HTTP_SUBREQUEST_BACKGROUND | NGX_HTTP_SUBREQUEST_IN_MEMORY;
+
+ 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;
+ }
+
+ ps->handler = ngx_http_js_subrequest_done;
+ ps->data = vm_event;
+
uri.len = uri_arg->length;
uri.data = uri_arg->start;
diff -r cb4f1052954f -r 6fccbc9f1288 src/njs.h
--- a/src/njs.h Thu Jan 16 15:14:38 2020 +0300
+++ b/src/njs.h Thu Jan 16 19:18:39 2020 +0300
@@ -102,6 +102,9 @@ struct njs_external_s {
};
+typedef njs_int_t (*njs_function_native_t) (njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t retval);
+
/*
* NJS and event loops.
*
@@ -238,6 +241,9 @@ NJS_EXPORT njs_int_t njs_vm_external_cre
NJS_EXPORT njs_external_ptr_t njs_vm_external(njs_vm_t *vm,
const njs_value_t *value);
+NJS_EXPORT njs_function_t *njs_vm_function_alloc(njs_vm_t *vm,
+ njs_function_native_t native);
+
NJS_EXPORT void njs_disassembler(njs_vm_t *vm);
NJS_EXPORT void njs_disassemble(u_char *start, u_char *end);
@@ -316,4 +322,8 @@ NJS_EXPORT njs_int_t njs_vm_json_parse(n
NJS_EXPORT njs_int_t njs_vm_json_stringify(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs);
+NJS_EXPORT njs_int_t njs_vm_promise_create(njs_vm_t *vm, njs_value_t *retval,
+ njs_value_t *callbacks);
+
+
#endif /* _NJS_H_INCLUDED_ */
diff -r cb4f1052954f -r 6fccbc9f1288 src/njs_function.c
--- a/src/njs_function.c Thu Jan 16 15:14:38 2020 +0300
+++ b/src/njs_function.c Thu Jan 16 19:18:39 2020 +0300
@@ -74,6 +74,24 @@ fail:
njs_function_t *
+njs_vm_function_alloc(njs_vm_t *vm, njs_function_native_t native)
+{
+ njs_function_t *function;
+
+ function = njs_mp_zalloc(vm->mem_pool, sizeof(njs_function_t));
+ if (njs_slow_path(function == NULL)) {
+ return NULL;
+ }
+
+ function->native = 1;
+ function->args_offset = 1;
+ function->u.native = native;
+
+ return function;
+}
+
+
+njs_function_t *
njs_function_value_copy(njs_vm_t *vm, njs_value_t *value)
{
njs_function_t *function, *copy;
diff -r cb4f1052954f -r 6fccbc9f1288 src/njs_promise.c
--- a/src/njs_promise.c Thu Jan 16 15:14:38 2020 +0300
+++ b/src/njs_promise.c Thu Jan 16 19:18:39 2020 +0300
@@ -140,6 +140,28 @@ njs_promise_constructor(njs_vm_t *vm, nj
}
+njs_int_t
+njs_vm_promise_create(njs_vm_t *vm, njs_value_t *retval, njs_value_t *callbacks)
+{
+ njs_int_t ret;
+ njs_promise_t *promise;
+
+ promise = njs_promise_alloc(vm);
+ if (njs_slow_path(promise == NULL)) {
+ return NJS_ERROR;
+ }
+
+ ret = njs_promise_create_resolving_functions(vm, promise, callbacks);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
+ }
+
+ njs_set_promise(retval, promise);
+
+ return NJS_OK;
+}
+
+
static njs_promise_t *
njs_promise_constructor_call(njs_vm_t *vm, njs_function_t *function)
{
diff -r cb4f1052954f -r 6fccbc9f1288 src/njs_value.h
--- a/src/njs_value.h Thu Jan 16 15:14:38 2020 +0300
+++ b/src/njs_value.h Thu Jan 16 19:18:39 2020 +0300
@@ -108,8 +108,6 @@ typedef struct njs_object_init_s nj
*/
typedef njs_int_t (*njs_prop_handler_t) (njs_vm_t *vm, njs_object_prop_t *prop,
njs_value_t *value, njs_value_t *setval, njs_value_t *retval);
-typedef njs_int_t (*njs_function_native_t) (njs_vm_t *vm, njs_value_t *args,
- njs_uint_t nargs, njs_index_t retval);
#if (!NJS_HAVE_GCC_ATTRIBUTE_ALIGNED)
#error "aligned attribute is required"
More information about the nginx-devel
mailing list