[nginx] Added helper function to set indexed variables.
Maxim Dounin
mdounin at mdounin.ru
Mon Jun 8 14:56:05 UTC 2026
details: http://freenginx.org/hg/nginx/rev/7d3b1378f3aa
branches:
changeset: 9554:7d3b1378f3aa
user: Maxim Dounin <mdounin at mdounin.ru>
date: Mon Jun 08 17:54:00 2026 +0300
description:
Added helper function to set indexed variables.
The ngx_http_set_indexed_variable() function correctly stores the
variable in r->variables[], and calls v->set_handler() if it is set
(which is now propagated to cmcf->variables).
This reduces amount of code needed in various places which set variables
(currently "set", "auth_request_set", and named captures), and also
unifies the behaviour across these places. Notable changes include:
- named captures now properly handle variables with v->set_handler(),
notably $limit_rate and $args, much like "set" currently does;
- the "auth_request_set" directive now does not update the value
in the r->variables cache if there is a set handler, similarly
to how "set" does, so invalid $limit_rate values are not returned
by subsequent variable lookups.
Similar changes were made in the stream module.
diffstat:
src/http/modules/ngx_http_auth_request_module.c | 27 +--------
src/http/modules/ngx_http_rewrite_module.c | 23 +-------
src/http/ngx_http_script.c | 38 +--------------
src/http/ngx_http_script.h | 8 ---
src/http/ngx_http_variables.c | 64 +++++++++++++++++-------
src/http/ngx_http_variables.h | 3 +
src/stream/ngx_stream_set_module.c | 18 +-----
src/stream/ngx_stream_variables.c | 60 ++++++++++++++++------
src/stream/ngx_stream_variables.h | 3 +
9 files changed, 106 insertions(+), 138 deletions(-)
diffs (457 lines):
diff --git a/src/http/modules/ngx_http_auth_request_module.c b/src/http/modules/ngx_http_auth_request_module.c
--- a/src/http/modules/ngx_http_auth_request_module.c
+++ b/src/http/modules/ngx_http_auth_request_module.c
@@ -26,7 +26,6 @@ typedef struct {
typedef struct {
ngx_int_t index;
ngx_http_complex_value_t value;
- ngx_http_set_variable_pt set_handler;
} ngx_http_auth_request_variable_t;
@@ -239,10 +238,8 @@ ngx_http_auth_request_set_variables(ngx_
ngx_http_auth_request_conf_t *arcf, ngx_http_auth_request_ctx_t *ctx)
{
ngx_str_t val;
- ngx_http_variable_t *v;
- ngx_http_variable_value_t *vv;
+ ngx_http_variable_value_t vv;
ngx_http_auth_request_variable_t *av, *last;
- ngx_http_core_main_conf_t *cmcf;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"auth request set variables");
@@ -251,9 +248,6 @@ ngx_http_auth_request_set_variables(ngx_
return NGX_OK;
}
- cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
- v = cmcf->variables.elts;
-
av = arcf->vars->elts;
last = av + arcf->vars->nelts;
@@ -263,27 +257,16 @@ ngx_http_auth_request_set_variables(ngx_
* internal redirects
*/
- vv = &r->variables[av->index];
-
if (ngx_http_complex_value(ctx->subrequest, &av->value, &val)
!= NGX_OK)
{
return NGX_ERROR;
}
- vv->valid = 1;
- vv->not_found = 0;
- vv->data = val.data;
- vv->len = val.len;
+ vv.data = val.data;
+ vv.len = val.len;
- if (av->set_handler) {
- /*
- * set_handler only available in cmcf->variables_keys, so we store
- * it explicitly
- */
-
- av->set_handler(r, vv, v[av->index].data);
- }
+ ngx_http_set_indexed_variable(r, av->index, &vv);
av++;
}
@@ -434,8 +417,6 @@ ngx_http_auth_request_set(ngx_conf_t *cf
v->get_handler = ngx_http_auth_request_variable;
}
- av->set_handler = v->set_handler;
-
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
ccv.cf = cf;
diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -893,11 +893,10 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx
{
ngx_http_rewrite_loc_conf_t *lcf = conf;
- ngx_int_t index;
- ngx_str_t *value;
- ngx_http_variable_t *v;
- ngx_http_script_var_code_t *vcode;
- ngx_http_script_var_handler_code_t *vhcode;
+ ngx_int_t index;
+ ngx_str_t *value;
+ ngx_http_variable_t *v;
+ ngx_http_script_var_code_t *vcode;
value = cf->args->elts;
@@ -930,20 +929,6 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx
return NGX_CONF_ERROR;
}
- if (v->set_handler) {
- vhcode = ngx_http_script_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_script_var_handler_code_t));
- if (vhcode == NULL) {
- return NGX_CONF_ERROR;
- }
-
- vhcode->code = ngx_http_script_var_set_handler_code;
- vhcode->handler = v->set_handler;
- vhcode->data = v->data;
-
- return NGX_CONF_OK;
- }
-
vcode = ngx_http_script_start_code(cf->pool, &lcf->codes,
sizeof(ngx_http_script_var_code_t));
if (vcode == NULL) {
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
@@ -1781,43 +1781,7 @@ ngx_http_script_set_var_code(ngx_http_sc
e->sp--;
- r->variables[code->index].len = e->sp->len;
- r->variables[code->index].valid = 1;
- r->variables[code->index].no_cacheable = 0;
- r->variables[code->index].not_found = 0;
- r->variables[code->index].data = e->sp->data;
-
-#if (NGX_DEBUG)
- {
- ngx_http_variable_t *v;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
-
- v = cmcf->variables.elts;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http script set $%V", &v[code->index].name);
- }
-#endif
-}
-
-
-void
-ngx_http_script_var_set_handler_code(ngx_http_script_engine_t *e)
-{
- ngx_http_script_var_handler_code_t *code;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http script set var handler");
-
- code = (ngx_http_script_var_handler_code_t *) e->ip;
-
- e->ip += sizeof(ngx_http_script_var_handler_code_t);
-
- e->sp--;
-
- code->handler(e->request, e->sp, code->data);
+ ngx_http_set_indexed_variable(r, code->index, e->sp);
}
diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h
--- a/src/http/ngx_http_script.h
+++ b/src/http/ngx_http_script.h
@@ -102,13 +102,6 @@ typedef struct {
typedef struct {
ngx_http_script_code_pt code;
- ngx_http_set_variable_pt handler;
- uintptr_t data;
-} ngx_http_script_var_handler_code_t;
-
-
-typedef struct {
- ngx_http_script_code_pt code;
uintptr_t n;
} ngx_http_script_copy_capture_code_t;
@@ -259,7 +252,6 @@ void ngx_http_script_file_code(ngx_http_
void ngx_http_script_complex_value_code(ngx_http_script_engine_t *e);
void ngx_http_script_value_code(ngx_http_script_engine_t *e);
void ngx_http_script_set_var_code(ngx_http_script_engine_t *e);
-void ngx_http_script_var_set_handler_code(ngx_http_script_engine_t *e);
void ngx_http_script_var_code(ngx_http_script_engine_t *e);
void ngx_http_script_nop_code(ngx_http_script_engine_t *e);
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -745,6 +745,43 @@ ngx_http_get_variable(ngx_http_request_t
}
+void
+ngx_http_set_indexed_variable(ngx_http_request_t *r, ngx_uint_t index,
+ ngx_http_variable_value_t *value)
+{
+ ngx_http_variable_t *v;
+ ngx_http_variable_value_t *vv;
+ ngx_http_core_main_conf_t *cmcf;
+
+ cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+ if (cmcf->variables.nelts <= index) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "unknown variable index: %ui", index);
+ return;
+ }
+
+ v = cmcf->variables.elts;
+
+ if (v[index].set_handler) {
+ v[index].set_handler(r, value, v[index].data);
+
+ } else {
+ vv = &r->variables[index];
+
+ vv->len = value->len;
+ vv->valid = 1;
+ vv->no_cacheable = 0;
+ vv->not_found = 0;
+ vv->escape = 0;
+ vv->data = value->data;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http set $%V to \"%v\"", &v[index].name, value);
+}
+
+
static ngx_int_t
ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v,
uintptr_t data)
@@ -2616,7 +2653,7 @@ ngx_http_regex_exec(ngx_http_request_t *
{
ngx_int_t rc, index;
ngx_uint_t i, n, len;
- ngx_http_variable_value_t *vv;
+ ngx_http_variable_value_t vv;
ngx_http_core_main_conf_t *cmcf;
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
@@ -2654,24 +2691,11 @@ ngx_http_regex_exec(ngx_http_request_t *
n = re->variables[i].capture;
index = re->variables[i].index;
- vv = &r->variables[index];
-
- vv->len = r->captures[n + 1] - r->captures[n];
- vv->valid = 1;
- vv->no_cacheable = 0;
- vv->not_found = 0;
- vv->data = &s->data[r->captures[n]];
-
-#if (NGX_DEBUG)
- {
- ngx_http_variable_t *v;
-
- v = cmcf->variables.elts;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http regex set $%V to \"%v\"", &v[index].name, vv);
- }
-#endif
+
+ vv.len = r->captures[n + 1] - r->captures[n];
+ vv.data = &s->data[r->captures[n]];
+
+ ngx_http_set_indexed_variable(r, index, &vv);
}
r->ncaptures = rc * 2;
@@ -2754,6 +2778,7 @@ ngx_http_variables_init_vars(ngx_conf_t
&& ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len)
== 0)
{
+ v[i].set_handler = av->set_handler;
v[i].get_handler = av->get_handler;
v[i].data = av->data;
@@ -2786,6 +2811,7 @@ ngx_http_variables_init_vars(ngx_conf_t
}
if (av) {
+ v[i].set_handler = av->set_handler;
v[i].get_handler = av->get_handler;
v[i].data = (uintptr_t) &v[i].name;
v[i].flags = av->flags;
diff --git a/src/http/ngx_http_variables.h b/src/http/ngx_http_variables.h
--- a/src/http/ngx_http_variables.h
+++ b/src/http/ngx_http_variables.h
@@ -57,6 +57,9 @@ ngx_http_variable_value_t *ngx_http_get_
ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r,
ngx_str_t *name, ngx_uint_t key);
+void ngx_http_set_indexed_variable(ngx_http_request_t *r, ngx_uint_t index,
+ ngx_http_variable_value_t *value);
+
ngx_int_t ngx_http_variable_unknown_header(ngx_http_request_t *r,
ngx_http_variable_value_t *v, ngx_str_t *var, ngx_list_part_t *part,
size_t prefix);
diff --git a/src/stream/ngx_stream_set_module.c b/src/stream/ngx_stream_set_module.c
--- a/src/stream/ngx_stream_set_module.c
+++ b/src/stream/ngx_stream_set_module.c
@@ -12,8 +12,6 @@
typedef struct {
ngx_int_t index;
- ngx_stream_set_variable_pt set_handler;
- uintptr_t data;
ngx_stream_complex_value_t value;
} ngx_stream_set_cmd_t;
@@ -90,18 +88,10 @@ ngx_stream_set_handler(ngx_stream_sessio
return NGX_ERROR;
}
- if (cmds[i].set_handler != NULL) {
- vv.len = str.len;
- vv.data = str.data;
- cmds[i].set_handler(s, &vv, cmds[i].data);
+ vv.len = str.len;
+ vv.data = str.data;
- } else {
- s->variables[cmds[i].index].len = str.len;
- s->variables[cmds[i].index].valid = 1;
- s->variables[cmds[i].index].no_cacheable = 0;
- s->variables[cmds[i].index].not_found = 0;
- s->variables[cmds[i].index].data = str.data;
- }
+ ngx_stream_set_indexed_variable(s, cmds[i].index, &vv);
}
return NGX_DECLINED;
@@ -209,8 +199,6 @@ ngx_stream_set(ngx_conf_t *cf, ngx_comma
}
set_cmd->index = index;
- set_cmd->set_handler = v->set_handler;
- set_cmd->data = v->data;
ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));
diff --git a/src/stream/ngx_stream_variables.c b/src/stream/ngx_stream_variables.c
--- a/src/stream/ngx_stream_variables.c
+++ b/src/stream/ngx_stream_variables.c
@@ -477,6 +477,43 @@ ngx_stream_get_variable(ngx_stream_sessi
}
+void
+ngx_stream_set_indexed_variable(ngx_stream_session_t *s, ngx_uint_t index,
+ ngx_stream_variable_value_t *value)
+{
+ ngx_stream_variable_t *v;
+ ngx_stream_variable_value_t *vv;
+ ngx_stream_core_main_conf_t *cmcf;
+
+ cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
+
+ if (cmcf->variables.nelts <= index) {
+ ngx_log_error(NGX_LOG_ALERT, s->connection->log, 0,
+ "unknown variable index: %ui", index);
+ return;
+ }
+
+ v = cmcf->variables.elts;
+
+ if (v[index].set_handler) {
+ v[index].set_handler(s, value, v[index].data);
+
+ } else {
+ vv = &s->variables[index];
+
+ vv->len = value->len;
+ vv->valid = 1;
+ vv->no_cacheable = 0;
+ vv->not_found = 0;
+ vv->escape = 0;
+ vv->data = value->data;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
+ "stream set $%V to \"%v\"", &v[index].name, value);
+}
+
+
static ngx_int_t
ngx_stream_variable_binary_remote_addr(ngx_stream_session_t *s,
ngx_stream_variable_value_t *v, uintptr_t data)
@@ -1100,7 +1137,7 @@ ngx_stream_regex_exec(ngx_stream_session
{
ngx_int_t rc, index;
ngx_uint_t i, n, len;
- ngx_stream_variable_value_t *vv;
+ ngx_stream_variable_value_t vv;
ngx_stream_core_main_conf_t *cmcf;
cmcf = ngx_stream_get_module_main_conf(s, ngx_stream_core_module);
@@ -1136,24 +1173,11 @@ ngx_stream_regex_exec(ngx_stream_session
n = re->variables[i].capture;
index = re->variables[i].index;
- vv = &s->variables[index];
-
- vv->len = s->captures[n + 1] - s->captures[n];
- vv->valid = 1;
- vv->no_cacheable = 0;
- vv->not_found = 0;
- vv->data = &str->data[s->captures[n]];
-#if (NGX_DEBUG)
- {
- ngx_stream_variable_t *v;
+ vv.len = s->captures[n + 1] - s->captures[n];
+ vv.data = &str->data[s->captures[n]];
- v = cmcf->variables.elts;
-
- ngx_log_debug2(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
- "stream regex set $%V to \"%v\"", &v[index].name, vv);
- }
-#endif
+ ngx_stream_set_indexed_variable(s, index, &vv);
}
s->ncaptures = rc * 2;
@@ -1236,6 +1260,7 @@ ngx_stream_variables_init_vars(ngx_conf_
&& ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len)
== 0)
{
+ v[i].set_handler = av->set_handler;
v[i].get_handler = av->get_handler;
v[i].data = av->data;
@@ -1268,6 +1293,7 @@ ngx_stream_variables_init_vars(ngx_conf_
}
if (av) {
+ v[i].set_handler = av->set_handler;
v[i].get_handler = av->get_handler;
v[i].data = (uintptr_t) &v[i].name;
v[i].flags = av->flags;
diff --git a/src/stream/ngx_stream_variables.h b/src/stream/ngx_stream_variables.h
--- a/src/stream/ngx_stream_variables.h
+++ b/src/stream/ngx_stream_variables.h
@@ -57,6 +57,9 @@ ngx_stream_variable_value_t *ngx_stream_
ngx_stream_variable_value_t *ngx_stream_get_variable(ngx_stream_session_t *s,
ngx_str_t *name, ngx_uint_t key);
+void ngx_stream_set_indexed_variable(ngx_stream_session_t *s, ngx_uint_t index,
+ ngx_stream_variable_value_t *value);
+
#if (NGX_PCRE)
More information about the nginx-devel
mailing list