[njs] Modules: added a session object for js_periodic handler.

Dmitry Volyntsev xeioex at nginx.com
Wed Sep 6 23:47:07 UTC 2023


details:   https://hg.nginx.org/njs/rev/0f1e76ab9d45
branches:  
changeset: 2191:0f1e76ab9d45
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Tue Sep 05 18:15:14 2023 -0700
description:
Modules: added a session object for js_periodic handler.

Now js_periodic handler is provided with a session object as its first
argument. Session object can be used to access variables created with
js_set, js_var or map directives.

example.conf:
    js_var $js_var  JS-VAR;

    location @periodics {
        js_periodic main.handler interval=60s;
    }

example.js:
    function handler(s) {
        ngx.log(ngx.INFO, s.variables.js_var);
    }

diffstat:

 nginx/ngx_http_js_module.c   |  115 +++++++++++++++++++++++++++++++++---------
 nginx/ngx_stream_js_module.c |  112 +++++++++++++++++++++++++++++++++--------
 nginx/t/js_periodic.t        |   37 +++++++++++-
 nginx/t/stream_js_periodic.t |   35 +++++++++++-
 ts/ngx_http_js_module.d.ts   |   22 ++++++++
 ts/ngx_stream_js_module.d.ts |   22 ++++++++
 6 files changed, 286 insertions(+), 57 deletions(-)

diffs (694 lines):

diff -r e3c442561889 -r 0f1e76ab9d45 nginx/ngx_http_js_module.c
--- a/nginx/ngx_http_js_module.c	Tue Sep 05 09:17:10 2023 -0700
+++ b/nginx/ngx_http_js_module.c	Tue Sep 05 18:15:14 2023 -0700
@@ -111,8 +111,7 @@ static ngx_int_t ngx_http_js_variable_se
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_js_variable_var(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,
-    unsigned inject_request);
+static ngx_int_t ngx_http_js_init_vm(ngx_http_request_t *r, njs_int_t proto_id);
 static void ngx_http_js_cleanup_ctx(void *data);
 
 static njs_int_t ngx_http_js_ext_keys_header(njs_vm_t *vm, njs_value_t *value,
@@ -217,6 +216,9 @@ static njs_int_t ngx_http_js_ext_keys_he
 static njs_int_t ngx_http_js_ext_variables(njs_vm_t *vm,
     njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
     njs_value_t *retval);
+static njs_int_t ngx_http_js_periodic_session_variables(njs_vm_t *vm,
+    njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
+    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,
@@ -494,6 +496,7 @@ static ngx_http_output_body_filter_pt   
 
 
 static njs_int_t    ngx_http_js_request_proto_id;
+static njs_int_t    ngx_http_js_periodic_session_proto_id;
 
 
 static njs_external_t  ngx_http_js_ext_request[] = {
@@ -817,6 +820,38 @@ static njs_external_t  ngx_http_js_ext_r
 };
 
 
+static njs_external_t  ngx_http_js_ext_periodic_session[] = {
+
+    {
+        .flags = NJS_EXTERN_PROPERTY | NJS_EXTERN_SYMBOL,
+        .name.symbol = NJS_SYMBOL_TO_STRING_TAG,
+        .u.property = {
+            .value = "PeriodicSession",
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_OBJECT,
+        .name.string = njs_str("rawVariables"),
+        .u.object = {
+            .writable = 1,
+            .prop_handler = ngx_http_js_periodic_session_variables,
+            .magic32 = NGX_JS_BUFFER,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_OBJECT,
+        .name.string = njs_str("variables"),
+        .u.object = {
+            .writable = 1,
+            .prop_handler = ngx_http_js_periodic_session_variables,
+            .magic32 = NGX_JS_STRING,
+        }
+    },
+};
+
+
 static njs_vm_ops_t ngx_http_js_ops = {
     ngx_http_js_set_timer,
     ngx_http_js_clear_timer,
@@ -904,7 +939,7 @@ ngx_http_js_content_event_handler(ngx_ht
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http js content event handler");
 
-    rc = ngx_http_js_init_vm(r, 1);
+    rc = ngx_http_js_init_vm(r, ngx_http_js_request_proto_id);
 
     if (rc == NGX_ERROR || rc == NGX_DECLINED) {
         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -1040,7 +1075,7 @@ ngx_http_js_header_filter(ngx_http_reque
         return ngx_http_next_header_filter(r);
     }
 
-    rc = ngx_http_js_init_vm(r, 1);
+    rc = ngx_http_js_init_vm(r, ngx_http_js_request_proto_id);
 
     if (rc == NGX_ERROR || rc == NGX_DECLINED) {
         return NGX_ERROR;
@@ -1092,7 +1127,7 @@ ngx_http_js_body_filter(ngx_http_request
         return ngx_http_next_body_filter(r, in);
     }
 
-    rc = ngx_http_js_init_vm(r, 1);
+    rc = ngx_http_js_init_vm(r, ngx_http_js_request_proto_id);
 
     if (rc == NGX_ERROR || rc == NGX_DECLINED) {
         return NGX_ERROR;
@@ -1206,7 +1241,7 @@ ngx_http_js_variable_set(ngx_http_reques
     ngx_str_t           value;
     ngx_http_js_ctx_t  *ctx;
 
-    rc = ngx_http_js_init_vm(r, 1);
+    rc = ngx_http_js_init_vm(r, ngx_http_js_request_proto_id);
 
     if (rc == NGX_ERROR) {
         return NGX_ERROR;
@@ -1280,7 +1315,7 @@ ngx_http_js_variable_var(ngx_http_reques
 
 
 static ngx_int_t
-ngx_http_js_init_vm(ngx_http_request_t *r, unsigned inject_request)
+ngx_http_js_init_vm(ngx_http_request_t *r, njs_int_t proto_id)
 {
     njs_int_t                rc;
     ngx_str_t                exception;
@@ -1359,12 +1394,10 @@ ngx_http_js_init_vm(ngx_http_request_t *
         return NGX_ERROR;
     }
 
-    if (inject_request) {
-        rc = njs_vm_external_create(ctx->vm, njs_value_arg(&ctx->request),
-                                    ngx_http_js_request_proto_id, r, 0);
-        if (rc != NJS_OK) {
-            return NGX_ERROR;
-        }
+    rc = njs_vm_external_create(ctx->vm, njs_value_arg(&ctx->request),
+                                proto_id, r, 0);
+    if (rc != NJS_OK) {
+        return NGX_ERROR;
     }
 
     return NGX_OK;
@@ -2904,24 +2937,17 @@ ngx_http_js_ext_keys_header_in(njs_vm_t 
 
 
 static njs_int_t
-ngx_http_js_ext_variables(njs_vm_t *vm, njs_object_prop_t *prop,
-    njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
+ngx_http_js_request_variables(njs_vm_t *vm, njs_object_prop_t *prop,
+    ngx_http_request_t *r, njs_value_t *setval, njs_value_t *retval)
 {
     njs_int_t                   rc;
     njs_str_t                   val, s;
     ngx_str_t                   name;
     ngx_uint_t                  key;
-    ngx_http_request_t         *r;
     ngx_http_variable_t        *v;
     ngx_http_core_main_conf_t  *cmcf;
     ngx_http_variable_value_t  *vv;
 
-    r = njs_vm_external(vm, ngx_http_js_request_proto_id, value);
-    if (r == NULL) {
-        njs_value_undefined_set(retval);
-        return NJS_DECLINED;
-    }
-
     rc = njs_vm_prop_name(vm, prop, &val);
     if (rc != NJS_OK) {
         njs_value_undefined_set(retval);
@@ -3001,6 +3027,38 @@ ngx_http_js_ext_variables(njs_vm_t *vm, 
 
 
 static njs_int_t
+ngx_http_js_ext_variables(njs_vm_t *vm, njs_object_prop_t *prop,
+    njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
+{
+    ngx_http_request_t  *r;
+
+    r = njs_vm_external(vm, ngx_http_js_request_proto_id, value);
+    if (r == NULL) {
+        njs_value_undefined_set(retval);
+        return NJS_DECLINED;
+    }
+
+    return ngx_http_js_request_variables(vm, prop, r, setval, retval);
+}
+
+
+static njs_int_t
+ngx_http_js_periodic_session_variables(njs_vm_t *vm, njs_object_prop_t *prop,
+    njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
+{
+    ngx_http_request_t  *r;
+
+    r = njs_vm_external(vm, ngx_http_js_periodic_session_proto_id, value);
+    if (r == NULL) {
+        njs_value_undefined_set(retval);
+        return NJS_DECLINED;
+    }
+
+    return ngx_http_js_request_variables(vm, prop, r, setval, retval);
+}
+
+
+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)
 {
@@ -4168,7 +4226,7 @@ ngx_http_js_periodic_handler(ngx_event_t
     r->health_check = 1;
     r->write_event_handler = ngx_http_js_periodic_write_event_handler;
 
-    rc = ngx_http_js_init_vm(r, 0);
+    rc = ngx_http_js_init_vm(r, ngx_http_js_periodic_session_proto_id);
 
     if (rc != NGX_OK) {
         ngx_http_js_periodic_destroy(r, periodic);
@@ -4181,8 +4239,8 @@ ngx_http_js_periodic_handler(ngx_event_t
 
     r->count++;
 
-    rc = ngx_js_invoke(ctx->vm, &periodic->method, &periodic->log, NULL, 0,
-                       &ctx->retval);
+    rc = ngx_js_invoke(ctx->vm, &periodic->method, &periodic->log,
+                       &ctx->request, 1, &ctx->retval);
 
     if (rc == NGX_AGAIN) {
         rc = NGX_OK;
@@ -4482,6 +4540,13 @@ ngx_js_http_init(njs_vm_t *vm)
         return NJS_ERROR;
     }
 
+    ngx_http_js_periodic_session_proto_id = njs_vm_external_prototype(vm,
+                                  ngx_http_js_ext_periodic_session,
+                                  njs_nitems(ngx_http_js_ext_periodic_session));
+    if (ngx_http_js_periodic_session_proto_id < 0) {
+        return NJS_ERROR;
+    }
+
     return NJS_OK;
 }
 
diff -r e3c442561889 -r 0f1e76ab9d45 nginx/ngx_stream_js_module.c
--- a/nginx/ngx_stream_js_module.c	Tue Sep 05 09:17:10 2023 -0700
+++ b/nginx/ngx_stream_js_module.c	Tue Sep 05 18:15:14 2023 -0700
@@ -88,7 +88,7 @@ static ngx_int_t ngx_stream_js_variable_
 static ngx_int_t ngx_stream_js_variable_var(ngx_stream_session_t *s,
     ngx_stream_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_stream_js_init_vm(ngx_stream_session_t *s,
-    unsigned inject_session);
+    njs_int_t proto_id);
 static void ngx_stream_js_drop_events(ngx_stream_js_ctx_t *ctx);
 static void ngx_stream_js_cleanup(void *data);
 static njs_int_t ngx_stream_js_run_event(ngx_stream_session_t *s,
@@ -117,6 +117,9 @@ static njs_int_t ngx_stream_js_ext_set_r
 static njs_int_t ngx_stream_js_ext_variables(njs_vm_t *vm,
     njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
     njs_value_t *retval);
+static njs_int_t ngx_stream_js_periodic_variables(njs_vm_t *vm,
+    njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval,
+    njs_value_t *retval);
 
 static njs_host_event_t ngx_stream_js_set_timer(njs_external_ptr_t external,
     uint64_t delay, njs_vm_event_t vm_event);
@@ -546,6 +549,38 @@ static njs_external_t  ngx_stream_js_ext
 };
 
 
+static njs_external_t  ngx_stream_js_ext_periodic_session[] = {
+
+    {
+        .flags = NJS_EXTERN_PROPERTY | NJS_EXTERN_SYMBOL,
+        .name.symbol = NJS_SYMBOL_TO_STRING_TAG,
+        .u.property = {
+            .value = "PeriodicSession",
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_OBJECT,
+        .name.string = njs_str("rawVariables"),
+        .u.object = {
+            .writable = 1,
+            .prop_handler = ngx_stream_js_periodic_variables,
+            .magic32 = NGX_JS_BUFFER,
+        }
+    },
+
+    {
+        .flags = NJS_EXTERN_OBJECT,
+        .name.string = njs_str("variables"),
+        .u.object = {
+            .writable = 1,
+            .prop_handler = ngx_stream_js_periodic_variables,
+            .magic32 = NGX_JS_STRING,
+        }
+    },
+};
+
+
 static njs_external_t  ngx_stream_js_ext_session_flags[] = {
 
     {
@@ -613,6 +648,7 @@ static ngx_stream_filter_pt  ngx_stream_
 
 
 static njs_int_t    ngx_stream_js_session_proto_id;
+static njs_int_t    ngx_stream_js_periodic_session_proto_id;
 static njs_int_t    ngx_stream_js_session_flags_proto_id;
 
 
@@ -686,7 +722,7 @@ ngx_stream_js_phase_handler(ngx_stream_s
         return NGX_DECLINED;
     }
 
-    rc = ngx_stream_js_init_vm(s, 1);
+    rc = ngx_stream_js_init_vm(s, ngx_stream_js_session_proto_id);
     if (rc != NGX_OK) {
         return rc;
     }
@@ -767,7 +803,7 @@ ngx_stream_js_body_filter(ngx_stream_ses
     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "stream js filter u:%ui",
                    from_upstream);
 
-    rc = ngx_stream_js_init_vm(s, 1);
+    rc = ngx_stream_js_init_vm(s, ngx_stream_js_session_proto_id);
 
     if (rc == NGX_ERROR) {
         return NGX_ERROR;
@@ -875,7 +911,7 @@ ngx_stream_js_variable_set(ngx_stream_se
     ngx_str_t             value;
     ngx_stream_js_ctx_t  *ctx;
 
-    rc = ngx_stream_js_init_vm(s, 1);
+    rc = ngx_stream_js_init_vm(s, ngx_stream_js_session_proto_id);
 
     if (rc == NGX_ERROR) {
         return NGX_ERROR;
@@ -949,7 +985,7 @@ ngx_stream_js_variable_var(ngx_stream_se
 
 
 static ngx_int_t
-ngx_stream_js_init_vm(ngx_stream_session_t *s, unsigned inject_session)
+ngx_stream_js_init_vm(ngx_stream_session_t *s, njs_int_t proto_id)
 {
     njs_int_t                  rc;
     njs_str_t                  key;
@@ -1026,12 +1062,10 @@ ngx_stream_js_init_vm(ngx_stream_session
         return NGX_ERROR;
     }
 
-    if (inject_session) {
-        rc = njs_vm_external_create(ctx->vm, njs_value_arg(&ctx->args[0]),
-                                    ngx_stream_js_session_proto_id, s, 0);
-        if (rc != NJS_OK) {
-            return NGX_ERROR;
-        }
+    rc = njs_vm_external_create(ctx->vm, njs_value_arg(&ctx->args[0]),
+                                proto_id, s, 0);
+    if (rc != NJS_OK) {
+        return NGX_ERROR;
     }
 
     return NGX_OK;
@@ -1507,24 +1541,17 @@ ngx_stream_js_ext_set_return_value(njs_v
 
 
 static njs_int_t
-ngx_stream_js_ext_variables(njs_vm_t *vm, njs_object_prop_t *prop,
-    njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
+ngx_stream_js_session_variables(njs_vm_t *vm, njs_object_prop_t *prop,
+    ngx_stream_session_t *s, njs_value_t *setval, njs_value_t *retval)
 {
     njs_int_t                     rc;
     njs_str_t                     val;
     ngx_str_t                     name;
     ngx_uint_t                    key;
     ngx_stream_variable_t        *v;
-    ngx_stream_session_t         *s;
     ngx_stream_core_main_conf_t  *cmcf;
     ngx_stream_variable_value_t  *vv;
 
-    s = njs_vm_external(vm, ngx_stream_js_session_proto_id, value);
-    if (s == NULL) {
-        njs_value_undefined_set(retval);
-        return NJS_DECLINED;
-    }
-
     rc = njs_vm_prop_name(vm, prop, &val);
     if (rc != NJS_OK) {
         njs_value_undefined_set(retval);
@@ -1601,6 +1628,38 @@ ngx_stream_js_ext_variables(njs_vm_t *vm
 }
 
 
+static njs_int_t
+ngx_stream_js_ext_variables(njs_vm_t *vm, njs_object_prop_t *prop,
+    njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
+{
+    ngx_stream_session_t  *s;
+
+    s = njs_vm_external(vm, ngx_stream_js_session_proto_id, value);
+    if (s == NULL) {
+        njs_value_undefined_set(retval);
+        return NJS_DECLINED;
+    }
+
+    return ngx_stream_js_session_variables(vm, prop, s, setval, retval);
+}
+
+
+static njs_int_t
+ngx_stream_js_periodic_variables(njs_vm_t *vm, njs_object_prop_t *prop,
+    njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
+{
+    ngx_stream_session_t  *s;
+
+    s = njs_vm_external(vm, ngx_stream_js_periodic_session_proto_id, value);
+    if (s == NULL) {
+        njs_value_undefined_set(retval);
+        return NJS_DECLINED;
+    }
+
+    return ngx_stream_js_session_variables(vm, prop, s, setval, retval);
+}
+
+
 static njs_host_event_t
 ngx_stream_js_set_timer(njs_external_ptr_t external, uint64_t delay,
     njs_vm_event_t vm_event)
@@ -1770,6 +1829,13 @@ ngx_js_stream_init(njs_vm_t *vm)
         return NJS_ERROR;
     }
 
+    ngx_stream_js_periodic_session_proto_id = njs_vm_external_prototype(vm,
+                                ngx_stream_js_ext_periodic_session,
+                                njs_nitems(ngx_stream_js_ext_periodic_session));
+    if (ngx_stream_js_periodic_session_proto_id < 0) {
+        return NJS_ERROR;
+    }
+
     ngx_stream_js_session_flags_proto_id = njs_vm_external_prototype(vm,
                                    ngx_stream_js_ext_session_flags,
                                    njs_nitems(ngx_stream_js_ext_session_flags));
@@ -1885,7 +1951,7 @@ ngx_stream_js_periodic_handler(ngx_event
 
     s->health_check = 1;
 
-    rc = ngx_stream_js_init_vm(s, 0);
+    rc = ngx_stream_js_init_vm(s, ngx_stream_js_periodic_session_proto_id);
 
     if (rc != NGX_OK) {
         ngx_stream_js_periodic_destroy(s, periodic);
@@ -1900,8 +1966,8 @@ ngx_stream_js_periodic_handler(ngx_event
 
     s->received++;
 
-    rc = ngx_js_invoke(ctx->vm, &periodic->method, &periodic->log, NULL, 0,
-                       &ctx->retval);
+    rc = ngx_js_invoke(ctx->vm, &periodic->method, &periodic->log,
+                       &ctx->args[0], 1, &ctx->retval);
 
     if (rc == NGX_AGAIN) {
         rc = NGX_OK;
diff -r e3c442561889 -r 0f1e76ab9d45 nginx/t/js_periodic.t
--- a/nginx/t/js_periodic.t	Tue Sep 05 09:17:10 2023 -0700
+++ b/nginx/t/js_periodic.t	Tue Sep 05 18:15:14 2023 -0700
@@ -45,6 +45,12 @@ http {
     js_shared_dict_zone zone=strings:32k;
     js_shared_dict_zone zone=workers:32k type=number;
 
+    js_set $js_set  test.js_set;
+    js_var $js_var  JS-VAR;
+    map _ $map_var {
+        default "MAP-VAR";
+    }
+
     server {
         listen       127.0.0.1:8080;
         server_name  localhost;
@@ -57,6 +63,7 @@ http {
             js_periodic test.fetch interval=40ms;
             js_periodic test.multiple_fetches interval=1s;
             js_periodic test.affinity interval=50ms worker_affinity=0101;
+            js_periodic test.vars interval=10s;
 
             js_periodic test.fetch_exception interval=1s;
             js_periodic test.tick_exception interval=1s;
@@ -99,6 +106,10 @@ http {
         location /test_timeout_exception {
             js_content test.test_timeout_exception;
         }
+
+        location /test_vars {
+            js_content test.test_vars;
+        }
     }
 }
 
@@ -121,6 +132,10 @@ my $p0 = port(8080);
         ngx.shared.strings.set('fetch', v + body);
     }
 
+    function js_set() {
+        return 'JS-SET';
+    }
+
     async function multiple_fetches() {
         let reply = await ngx.fetch('http://127.0.0.1:$p0/fetch_ok');
         let reply2 = await ngx.fetch('http://127.0.0.1:$p0/fetch_foo');
@@ -181,6 +196,12 @@ my $p0 = port(8080);
         }, 1);
     }
 
+    function vars(s) {
+        var v = s.variables;
+        ngx.shared.strings.set('vars',
+                               `\${v.js_var}|\${v.js_set}|\${v.map_var}`);
+    }
+
     function test_affinity(r) {
         r.return(200, `[\${ngx.shared.workers.keys().toSorted()}]`);
     }
@@ -211,14 +232,19 @@ my $p0 = port(8080);
         r.return(200, ngx.shared.nums.get('timeout_exception') >= 2);
     }
 
-    export default { affinity, fetch, fetch_exception, file, multiple_fetches,
-                     overrun, test_affinity, test_fetch, test_file,
-                     test_multiple_fetches, test_tick, test_timeout_exception,
-                     test_timer, tick, tick_exception, timer, timer_exception,
+    function test_vars(r) {
+        r.return(200, ngx.shared.strings.get('vars'));
+    }
+
+    export default { affinity, fetch, fetch_exception, file, js_set,
+                     multiple_fetches, overrun, vars, test_affinity, test_fetch,
+                     test_file, test_multiple_fetches, test_tick,
+                     test_timeout_exception, test_timer, test_vars, tick,
+                     tick_exception, timer, timer_exception,
                      timeout_exception };
 EOF
 
-$t->try_run('no js_periodic')->plan(8);
+$t->try_run('no js_periodic')->plan(9);
 
 ###############################################################################
 
@@ -232,6 +258,7 @@ like(http_get('/test_fetch'), qr/true/, 
 like(http_get('/test_multiple_fetches'), qr/true/, 'multiple fetch test');
 
 like(http_get('/test_timeout_exception'), qr/true/, 'timeout exception test');
+like(http_get('/test_vars'), qr/JS-VAR\|JS-SET\|MAP-VAR/, 'vars test');
 
 $t->stop();
 
diff -r e3c442561889 -r 0f1e76ab9d45 nginx/t/stream_js_periodic.t
--- a/nginx/t/stream_js_periodic.t	Tue Sep 05 09:17:10 2023 -0700
+++ b/nginx/t/stream_js_periodic.t	Tue Sep 05 18:15:14 2023 -0700
@@ -46,6 +46,12 @@ stream {
     js_shared_dict_zone zone=strings:32k;
     js_shared_dict_zone zone=workers:32k type=number;
 
+    js_set $js_set  test.js_set;
+    js_var $js_var  JS-VAR;
+    map _ $map_var {
+        default "MAP-VAR";
+    }
+
     server {
         listen       127.0.0.1:8080;
 
@@ -56,6 +62,7 @@ stream {
         js_periodic test.fetch interval=40ms;
         js_periodic test.multiple_fetches interval=1s;
         js_periodic test.affinity interval=50ms worker_affinity=0101;
+        js_periodic test.vars interval=10s;
 
         js_periodic test.fetch_exception interval=1s;
         js_periodic test.tick_exception interval=1s;
@@ -108,6 +115,10 @@ my $p1 = port(8081);
         let reply = await ngx.fetch('garbage');
      }
 
+    function js_set() {
+        return 'JS-SET';
+    }
+
     async function multiple_fetches() {
         let reply = await ngx.fetch('http://127.0.0.1:$p1/fetch_ok');
         let reply2 = await ngx.fetch('http://127.0.0.1:$p1/fetch_foo');
@@ -163,6 +174,12 @@ my $p1 = port(8081);
         }, 1);
     }
 
+    function vars(s) {
+        var v = s.variables;
+        ngx.shared.strings.set('vars',
+                               `\${v.js_var}|\${v.js_set}|\${v.map_var}`);
+    }
+
     function test(s) {
         s.on('upload', function (data) {
             if (data.length > 0) {
@@ -229,6 +246,15 @@ my $p1 = port(8081);
 
                     break;
 
+                case 'vars':
+                    var vars = ngx.shared.strings.get('vars');
+                    if (vars === 'JS-VAR|JS-SET|MAP-VAR') {
+                        s.done();
+                        return;
+                    }
+
+                    break;
+
                 default:
                     throw new Error(`Unknown test "\${data}"`);
                 }
@@ -238,13 +264,13 @@ my $p1 = port(8081);
         });
     }
 
-    export default { affinity, fetch, fetch_exception, multiple_fetches, file,
-                     overrun, test, tick, tick_exception, timer,
-                     timer_exception, timeout_exception };
+    export default { affinity, fetch, fetch_exception, js_set, multiple_fetches,
+                     file, overrun, test, tick, tick_exception, timer,
+                     timer_exception, timeout_exception, vars };
 EOF
 
 $t->run_daemon(\&stream_daemon, port(8090));
-$t->try_run('no js_periodic')->plan(8);
+$t->try_run('no js_periodic')->plan(9);
 $t->waitforsocket('127.0.0.1:' . port(8090));
 
 ###############################################################################
@@ -261,6 +287,7 @@ is(stream('127.0.0.1:' . port(8080))->io
 	'multiple_fetches', 'muliple fetches test');
 is(stream('127.0.0.1:' . port(8080))->io('timeout_exception'),
 	'timeout_exception', 'timeout exception test');
+is(stream('127.0.0.1:' . port(8080))->io('vars'), 'vars', 'vars test');
 
 $t->stop();
 
diff -r e3c442561889 -r 0f1e76ab9d45 ts/ngx_http_js_module.d.ts
--- a/ts/ngx_http_js_module.d.ts	Tue Sep 05 09:17:10 2023 -0700
+++ b/ts/ngx_http_js_module.d.ts	Tue Sep 05 18:15:14 2023 -0700
@@ -479,3 +479,25 @@ interface NginxHTTPRequest {
      */
     warn(message: NjsStringOrBuffer): void;
 }
+
+
+/**
+ * NginxPeriodicSession object is available as the first argument in the js_periodic handler.
+ * @since 0.8.1
+ */
+interface NginxPeriodicSession {
+    /**
+     * nginx variables as Buffers.
+     *
+     * @see variables
+     */
+    readonly rawVariables: NginxRawVariables;
+    /**
+     * nginx variables as strings.
+     *
+     * **Warning:** Bytes invalid in UTF-8 encoding may be converted into the replacement character.
+     *
+     * @see rawVariables
+     */
+    readonly variables: NginxVariables;
+}
diff -r e3c442561889 -r 0f1e76ab9d45 ts/ngx_stream_js_module.d.ts
--- a/ts/ngx_stream_js_module.d.ts	Tue Sep 05 09:17:10 2023 -0700
+++ b/ts/ngx_stream_js_module.d.ts	Tue Sep 05 18:15:14 2023 -0700
@@ -211,3 +211,25 @@ interface NginxStreamRequest {
      */
     warn(message: NjsStringOrBuffer): void;
 }
+
+
+/**
+ * NginxPeriodicSession object is available as the first argument in the js_periodic handler.
+ * @since 0.8.1
+ */
+interface NginxPeriodicSession {
+    /**
+     * nginx variables as Buffers.
+     *
+     * @see variables
+     */
+    readonly rawVariables: NginxRawVariables;
+    /**
+     * nginx variables as strings.
+     *
+     * **Warning:** Bytes invalid in UTF-8 encoding may be converted into the replacement character.
+     *
+     * @see rawVariables
+     */
+    readonly variables: NginxVariables;
+}


More information about the nginx-devel mailing list