[nginx] Script: flushing now implies lookup of variables.

Maxim Dounin mdounin at mdounin.ru
Sat Jul 25 00:04:55 UTC 2026


details:   http://freenginx.org/hg/nginx/rev/b9068e5a711c
branches:  
changeset: 9578:b9068e5a711c
user:      Maxim Dounin <mdounin at mdounin.ru>
date:      Sun Jul 19 00:47:45 2026 +0300
description:
Script: flushing now implies lookup of variables.

Now flushing variables, such as in ngx_http_complex_value() and in
ngx_http_script_flush_no_cacheable_variables(), not only clears existing
cached values, but also looks up new values by calling
ngx_http_get_flushed_variable() for all relevant variables.

This ensures that even when there are variables with side effects,
proper lengths of all variables are available during length
calculations.  In particular, this fixes issues observed in the
following configuration:

    map $uri $map {
        ~(?<capture>.*) $capture;
    }

    return 200 $capture$map;

Note that this requires changes to the proxy module, which does flushing
before the actual variable values are known.  But the code in the proxy
module is incorrect anyway, and using the $proxy_internal_body_length
variable in the proxy_set_body will break things.

Similar changes were made in the stream module.

diffstat:

 src/http/modules/ngx_http_proxy_module.c |   7 ++++---
 src/http/ngx_http_script.c               |  12 ++----------
 src/stream/ngx_stream_script.c           |  12 ++----------
 3 files changed, 8 insertions(+), 23 deletions(-)

diffs (83 lines):

diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -1340,10 +1340,9 @@ ngx_http_proxy_create_request(ngx_http_r
 
     ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
 
-    ngx_http_script_flush_no_cacheable_variables(r, plcf->body_flushes);
-    ngx_http_script_flush_no_cacheable_variables(r, headers->flushes);
-
     if (plcf->body_lengths) {
+        ngx_http_script_flush_no_cacheable_variables(r, plcf->body_flushes);
+
         le.ip = plcf->body_lengths->elts;
         le.request = r;
         le.flushed = 1;
@@ -1367,6 +1366,8 @@ ngx_http_proxy_create_request(ngx_http_r
         ctx->internal_body_length = r->headers_in.content_length_n;
     }
 
+    ngx_http_script_flush_no_cacheable_variables(r, headers->flushes);
+
     le.ip = headers->lengths->elts;
     le.request = r;
     le.flushed = 1;
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -41,12 +41,7 @@ ngx_http_script_flush_complex_value(ngx_
 
     if (index) {
         while (*index != (ngx_uint_t) -1) {
-
-            if (r->variables[*index].no_cacheable) {
-                r->variables[*index].valid = 0;
-                r->variables[*index].not_found = 0;
-            }
-
+            (void) ngx_http_get_flushed_variable(r, *index);
             index++;
         }
     }
@@ -665,10 +660,7 @@ ngx_http_script_flush_no_cacheable_varia
     if (indices) {
         index = indices->elts;
         for (n = 0; n < indices->nelts; n++) {
-            if (r->variables[index[n]].no_cacheable) {
-                r->variables[index[n]].valid = 0;
-                r->variables[index[n]].not_found = 0;
-            }
+            (void) ngx_http_get_flushed_variable(r, index[n]);
         }
     }
 }
diff --git a/src/stream/ngx_stream_script.c b/src/stream/ngx_stream_script.c
--- a/src/stream/ngx_stream_script.c
+++ b/src/stream/ngx_stream_script.c
@@ -41,12 +41,7 @@ ngx_stream_script_flush_complex_value(ng
 
     if (index) {
         while (*index != (ngx_uint_t) -1) {
-
-            if (s->variables[*index].no_cacheable) {
-                s->variables[*index].valid = 0;
-                s->variables[*index].not_found = 0;
-            }
-
+            (void) ngx_stream_get_flushed_variable(s, *index);
             index++;
         }
     }
@@ -547,10 +542,7 @@ ngx_stream_script_flush_no_cacheable_var
     if (indices) {
         index = indices->elts;
         for (n = 0; n < indices->nelts; n++) {
-            if (s->variables[index[n]].no_cacheable) {
-                s->variables[index[n]].valid = 0;
-                s->variables[index[n]].not_found = 0;
-            }
+            (void) ngx_stream_get_flushed_variable(s, index[n]);
         }
     }
 }


More information about the nginx-devel mailing list