Skip to content

Commit

Permalink
HTTP: simplifed r.subrequest() code.
Browse files Browse the repository at this point in the history
Moving promise callbacks from ctx->promise_callbacks to
the arguments of ngx_js_event_t.
  • Loading branch information
xeioex committed Jul 2, 2024
1 parent c773ebc commit 7dda4b2
Showing 1 changed file with 71 additions and 175 deletions.
246 changes: 71 additions & 175 deletions nginx/ngx_http_js_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ typedef struct {
njs_opaque_value_t request_body;
njs_opaque_value_t response_body;
ngx_str_t redirect_uri;
ngx_array_t promise_callbacks;

ngx_int_t filter;
ngx_buf_t *buf;
Expand Down Expand Up @@ -216,9 +215,6 @@ static njs_int_t ngx_http_js_periodic_session_variables(njs_vm_t *vm,
njs_value_t *retval);
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, njs_value_t *retval);
static ngx_int_t ngx_http_js_subrequest(ngx_http_request_t *r,
njs_str_t *uri_arg, njs_str_t *args_arg, njs_function_t *callback,
ngx_http_request_t **sr);
static ngx_int_t ngx_http_js_subrequest_done(ngx_http_request_t *r,
void *data, ngx_int_t rc);
static njs_int_t ngx_http_js_ext_get_parent(njs_vm_t *vm,
Expand Down Expand Up @@ -3049,74 +3045,23 @@ ngx_http_js_periodic_session_variables(njs_vm_t *vm, njs_object_prop_t *prop,
}


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_value_t *retval)
{
ngx_uint_t i;
njs_function_t *callback;
ngx_http_js_cb_t *cb, *cbs;
ngx_http_js_ctx_t *ctx;
ngx_http_request_t *r;

r = njs_vm_external(vm, ngx_http_js_request_proto_id,
njs_arg(args, nargs, 1));
ctx = ngx_http_get_module_ctx(r->parent, ngx_http_js_module);

ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"js subrequest promise trampoline parent ctx: %p", ctx);

if (ctx == NULL) {
njs_vm_error(vm, "js subrequest: failed to get the parent context");
return NJS_ERROR;
}

cbs = ctx->promise_callbacks.elts;

if (cbs == NULL) {
goto fail;
}

cb = NULL;

for (i = 0; i < ctx->promise_callbacks.nelts; i++) {
if (cbs[i].request == r) {
cb = &cbs[i];
cb->request = NULL;
break;
}
}

if (cb == NULL) {
goto fail;
}

callback = njs_value_function(njs_value_arg(&cb->callbacks[0]));

return njs_vm_call(vm, callback, njs_argument(args, 1), 1);

fail:

njs_vm_error(vm, "js subrequest: promise callback not found");

return NJS_ERROR;
}


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, njs_value_t *retval)
{
ngx_int_t rc, promise;
njs_str_t uri_arg, args_arg, method_name, body_arg;
ngx_uint_t i, method, methods_max, has_body, detached;
njs_value_t *value, *arg, *options;
njs_function_t *callback;
ngx_http_js_cb_t *cb, *cbs;
ngx_http_js_ctx_t *ctx;
njs_opaque_value_t lvalue;
ngx_http_request_t *r, *sr;
ngx_http_request_body_t *rb;
ngx_int_t rc, flags;
njs_str_t uri_arg, args_arg, method_name, body_arg;
ngx_str_t uri, rargs;
ngx_uint_t method, methods_max, has_body, detached,
promise;
njs_value_t *value, *arg, *options;
ngx_js_event_t *event;
njs_function_t *callback;
ngx_http_js_ctx_t *ctx;
njs_opaque_value_t lvalue;
ngx_http_request_t *r, *sr;
ngx_http_request_body_t *rb;
ngx_http_post_subrequest_t *ps;

static const struct {
ngx_str_t name;
Expand Down Expand Up @@ -3178,7 +3123,6 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
args_arg.length = 0;
args_arg.start = NULL;
has_body = 0;
promise = 0;
detached = 0;

arg = njs_arg(args, nargs, 2);
Expand Down Expand Up @@ -3267,21 +3211,71 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
return NJS_ERROR;
}

if (!detached && callback == NULL) {
callback = njs_vm_function_alloc(vm, ngx_http_js_promise_trampoline, 0,
0);
if (callback == NULL) {
goto memory_error;
promise = 0;
flags = NGX_HTTP_SUBREQUEST_BACKGROUND;

njs_value_undefined_set(retval);

if (!detached) {
ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
if (ps == NULL) {
njs_vm_memory_error(ctx->vm);
return NJS_ERROR;
}

promise = !!(callback == NULL);

event = njs_mp_zalloc(njs_vm_memory_pool(ctx->vm),
sizeof(ngx_js_event_t)
+ promise * (sizeof(njs_opaque_value_t) * 2));
if (njs_slow_path(event == NULL)) {
njs_vm_memory_error(ctx->vm);
return NJS_ERROR;
}

promise = 1;
event->vm = ctx->vm;
event->fd = ctx->event_id++;

if (promise) {
event->args = (njs_value_t *) &event[1];
rc = njs_vm_promise_create(ctx->vm, retval,
njs_value_arg(event->args));
if (rc != NJS_OK) {
return NJS_ERROR;
}

callback = njs_value_function(njs_value_arg(event->args));
}

event->function = callback;

ps->handler = ngx_http_js_subrequest_done;
ps->data = event;

flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY;

} else {
ps = NULL;
event = NULL;
}

rc = ngx_http_js_subrequest(r, &uri_arg, &args_arg, callback, &sr);
if (rc != NGX_OK) {
uri.len = uri_arg.length;
uri.data = uri_arg.start;

rargs.len = args_arg.length;
rargs.data = args_arg.start;

if (ngx_http_subrequest(r, &uri, rargs.len ? &rargs : NULL, &sr, ps, flags)
!= NGX_OK)
{
njs_vm_error(ctx->vm, "subrequest creation failed");
return NJS_ERROR;
}

if (event != NULL) {
ngx_js_add_event(ctx, event);
}

if (method != methods_max) {
sr->method = methods[method].value;
sr->method_name = methods[method].name;
Expand Down Expand Up @@ -3325,41 +3319,6 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
sr->headers_in.chunked = 0;
}

if (promise) {
cbs = ctx->promise_callbacks.elts;

if (cbs == NULL) {
if (ngx_array_init(&ctx->promise_callbacks, r->pool, 4,
sizeof(ngx_http_js_cb_t)) != NGX_OK)
{
goto memory_error;
}
}

cb = NULL;

for (i = 0; i < ctx->promise_callbacks.nelts; i++) {
if (cbs[i].request == NULL) {
cb = &cbs[i];
break;
}
}

if (i == ctx->promise_callbacks.nelts) {
cb = ngx_array_push(&ctx->promise_callbacks);
if (cb == NULL) {
goto memory_error;
}
}

cb->request = sr;

return njs_vm_promise_create(vm, retval,
njs_value_arg(&cb->callbacks));
}

njs_value_undefined_set(retval);

return NJS_OK;

memory_error:
Expand All @@ -3370,69 +3329,6 @@ ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
}


static ngx_int_t
ngx_http_js_subrequest(ngx_http_request_t *r, njs_str_t *uri_arg,
njs_str_t *args_arg, njs_function_t *callback, ngx_http_request_t **sr)
{
ngx_int_t flags;
ngx_str_t uri, args;
ngx_js_event_t *event;
ngx_http_js_ctx_t *ctx;
ngx_http_post_subrequest_t *ps;

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;
}

event = njs_mp_zalloc(njs_vm_memory_pool(ctx->vm),
sizeof(ngx_js_event_t));
if (njs_slow_path(event == NULL)) {
njs_vm_memory_error(ctx->vm);
return NJS_ERROR;
}

event->vm = ctx->vm;
event->function = callback;
event->fd = ctx->event_id++;

ps->handler = ngx_http_js_subrequest_done;
ps->data = event;

flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY;

} else {
ps = NULL;
event = NULL;
}

uri.len = uri_arg->length;
uri.data = uri_arg->start;

args.len = args_arg->length;
args.data = args_arg->start;

if (ngx_http_subrequest(r, &uri, args.len ? &args : NULL, sr, ps, flags)
!= NGX_OK)
{
njs_vm_error(ctx->vm, "subrequest creation failed");
return NJS_ERROR;
}

if (event != NULL) {
ngx_js_add_event(ctx, event);
}

return NJS_OK;
}


static ngx_int_t
ngx_http_js_subrequest_done(ngx_http_request_t *r, void *data, ngx_int_t rc)
{
Expand Down

0 comments on commit 7dda4b2

Please sign in to comment.