From 59fe491adb93b7aa75597456eafcc14cb451f506 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Mon, 1 Feb 2021 12:24:17 +0000 Subject: [PATCH] HTTP: added js header filter. --- nginx/config | 2 +- nginx/ngx_http_js_module.c | 69 +++++++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/nginx/config b/nginx/config index 5b9012bb..6389ae40 100644 --- a/nginx/config +++ b/nginx/config @@ -5,7 +5,7 @@ NJS_SRCS="$ngx_addon_dir/ngx_js.c \ $ngx_addon_dir/ngx_js_fetch.c" if [ $HTTP != NO ]; then - ngx_module_type=HTTP + ngx_module_type=HTTP_FILTER ngx_module_name=ngx_http_js_module ngx_module_incs="$ngx_addon_dir/../src $ngx_addon_dir/../build" ngx_module_deps="$ngx_addon_dir/../build/libnjs.a $NJS_DEPS" diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index 56001789..60dc8f98 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -24,6 +24,7 @@ typedef struct { typedef struct { ngx_str_t content; + ngx_str_t header_filter; } ngx_http_js_loc_conf_t; @@ -76,6 +77,7 @@ static void ngx_http_js_content_event_handler(ngx_http_request_t *r); static void ngx_http_js_content_write_event_handler(ngx_http_request_t *r); static void ngx_http_js_content_finalize(ngx_http_request_t *r, ngx_http_js_ctx_t *ctx); +static ngx_int_t ngx_http_js_header_filter(ngx_http_request_t *r); static ngx_int_t ngx_http_js_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_js_init_vm(ngx_http_request_t *r); @@ -189,6 +191,7 @@ static void ngx_http_js_handle_vm_event(ngx_http_request_t *r, static void ngx_http_js_handle_event(ngx_http_request_t *r, njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs); +static ngx_int_t ngx_http_js_init(ngx_conf_t *cf); static char *ngx_http_js_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_js_import(ngx_conf_t *cf, ngx_command_t *cmd, @@ -240,13 +243,20 @@ static ngx_command_t ngx_http_js_commands[] = { 0, NULL }, + { ngx_string("js_header_filter"), + NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_js_loc_conf_t, header_filter), + NULL }, + ngx_null_command }; static ngx_http_module_t ngx_http_js_module_ctx = { NULL, /* preconfiguration */ - NULL, /* postconfiguration */ + ngx_http_js_init, /* postconfiguration */ ngx_http_js_create_main_conf, /* create main configuration */ ngx_http_js_init_main_conf, /* init main configuration */ @@ -275,6 +285,9 @@ ngx_module_t ngx_http_js_module = { }; +static ngx_http_output_header_filter_pt ngx_http_next_header_filter; + + static njs_external_t ngx_http_js_ext_request[] = { { @@ -736,6 +749,48 @@ ngx_http_js_content_finalize(ngx_http_request_t *r, ngx_http_js_ctx_t *ctx) } +static ngx_int_t +ngx_http_js_header_filter(ngx_http_request_t *r) +{ + ngx_int_t rc; + njs_int_t pending; + ngx_http_js_ctx_t *ctx; + ngx_http_js_loc_conf_t *jlcf; + + jlcf = ngx_http_get_module_loc_conf(r, ngx_http_js_module); + + if (jlcf->header_filter.len == 0) { + return ngx_http_next_header_filter(r); + } + + rc = ngx_http_js_init_vm(r); + + if (rc == NGX_ERROR || rc == NGX_DECLINED) { + return NGX_ERROR; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); + + pending = njs_vm_pending(ctx->vm); + + rc = ngx_js_call(ctx->vm, &jlcf->header_filter, &ctx->request, + r->connection->log); + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + if (!pending && rc == NGX_AGAIN) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "async operation inside \"%V\" header filter", + &jlcf->header_filter); + return NGX_ERROR; + } + + return ngx_http_next_header_filter(r); +} + + static ngx_int_t ngx_http_js_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) @@ -3220,6 +3275,16 @@ ngx_http_js_init_main_conf(ngx_conf_t *cf, void *conf) } +static ngx_int_t +ngx_http_js_init(ngx_conf_t *cf) +{ + ngx_http_next_header_filter = ngx_http_top_header_filter; + ngx_http_top_header_filter = ngx_http_js_header_filter; + + return NGX_OK; +} + + static char * ngx_http_js_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { @@ -3444,6 +3509,7 @@ ngx_http_js_create_loc_conf(ngx_conf_t *cf) * set by ngx_pcalloc(): * * conf->content = { 0, NULL }; + * conf->header_filter = { 0, NULL }; */ return conf; @@ -3457,6 +3523,7 @@ ngx_http_js_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_http_js_loc_conf_t *conf = child; ngx_conf_merge_str_value(conf->content, prev->content, ""); + ngx_conf_merge_str_value(conf->header_filter, prev->header_filter, ""); return NGX_CONF_OK; } -- 2.47.3