]> git.kaiwu.me - njs.git/commitdiff
HTTP: added js header filter.
authorDmitry Volyntsev <xeioex@nginx.com>
Mon, 1 Feb 2021 12:24:17 +0000 (12:24 +0000)
committerDmitry Volyntsev <xeioex@nginx.com>
Mon, 1 Feb 2021 12:24:17 +0000 (12:24 +0000)
nginx/config
nginx/ngx_http_js_module.c

index 5b9012bbab49fc905fa212c9a0bd63c500a4d947..6389ae4029e48db7abe09ff2ac9ea85a0420020d 100644 (file)
@@ -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"
index 5600178968a8c0d9bd8ac2586d23877adf469303..60dc8f989d58d1b0503545f9d531c914849856d7 100644 (file)
@@ -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;
 }