diff options
Diffstat (limited to 'src/stream/ngx_stream_variables.c')
-rw-r--r-- | src/stream/ngx_stream_variables.c | 146 |
1 files changed, 125 insertions, 21 deletions
diff --git a/src/stream/ngx_stream_variables.c b/src/stream/ngx_stream_variables.c index 9dc93ee57..5d15f3a6d 100644 --- a/src/stream/ngx_stream_variables.c +++ b/src/stream/ngx_stream_variables.c @@ -10,6 +10,8 @@ #include <ngx_stream.h> #include <nginx.h> +static ngx_stream_variable_t *ngx_stream_add_prefix_variable(ngx_conf_t *cf, + ngx_str_t *name, ngx_uint_t flags); static ngx_int_t ngx_stream_variable_binary_remote_addr( ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); @@ -137,6 +139,10 @@ ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) return NULL; } + if (flags & NGX_STREAM_VAR_PREFIX) { + return ngx_stream_add_prefix_variable(cf, name, flags); + } + cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); key = cmcf->variables_keys->keys.elts; @@ -155,6 +161,8 @@ ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) return NULL; } + v->flags &= flags | ~NGX_STREAM_VAR_WEAK; + return v; } @@ -193,6 +201,60 @@ ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) } +static ngx_stream_variable_t * +ngx_stream_add_prefix_variable(ngx_conf_t *cf, ngx_str_t *name, + ngx_uint_t flags) +{ + ngx_uint_t i; + ngx_stream_variable_t *v; + ngx_stream_core_main_conf_t *cmcf; + + cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); + + v = cmcf->prefix_variables.elts; + for (i = 0; i < cmcf->prefix_variables.nelts; i++) { + if (name->len != v[i].name.len + || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) + { + continue; + } + + v = &v[i]; + + if (!(v->flags & NGX_STREAM_VAR_CHANGEABLE)) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the duplicate \"%V\" variable", name); + return NULL; + } + + v->flags &= flags | ~NGX_STREAM_VAR_WEAK; + + return v; + } + + v = ngx_array_push(&cmcf->prefix_variables); + if (v == NULL) { + return NULL; + } + + v->name.len = name->len; + v->name.data = ngx_pnalloc(cf->pool, name->len); + if (v->name.data == NULL) { + return NULL; + } + + ngx_strlow(v->name.data, name->data, name->len); + + v->set_handler = NULL; + v->get_handler = NULL; + v->data = 0; + v->flags = flags; + v->index = 0; + + return v; +} + + ngx_int_t ngx_stream_get_variable_index(ngx_conf_t *cf, ngx_str_t *name) { @@ -327,6 +389,8 @@ ngx_stream_variable_value_t * ngx_stream_get_variable(ngx_stream_session_t *s, ngx_str_t *name, ngx_uint_t key) { + size_t len; + ngx_uint_t i, n; ngx_stream_variable_t *v; ngx_stream_variable_value_t *vv; ngx_stream_core_main_conf_t *cmcf; @@ -365,6 +429,28 @@ ngx_stream_get_variable(ngx_stream_session_t *s, ngx_str_t *name, return NULL; } + len = 0; + + v = cmcf->prefix_variables.elts; + n = cmcf->prefix_variables.nelts; + + for (i = 0; i < cmcf->prefix_variables.nelts; i++) { + if (name->len >= v[i].name.len && name->len > len + && ngx_strncmp(name->data, v[i].name.data, v[i].name.len) == 0) + { + len = v[i].name.len; + n = i; + } + } + + if (n != cmcf->prefix_variables.nelts) { + if (v[n].get_handler(s, vv, (uintptr_t) name) == NGX_OK) { + return vv; + } + + return NULL; + } + vv->not_found = 1; return vv; @@ -1000,7 +1086,6 @@ ngx_stream_regex_exec(ngx_stream_session_t *s, ngx_stream_regex_t *re, ngx_int_t ngx_stream_variables_add_core_vars(ngx_conf_t *cf) { - ngx_int_t rc; ngx_stream_variable_t *cv, *v; ngx_stream_core_main_conf_t *cmcf; @@ -1021,27 +1106,20 @@ ngx_stream_variables_add_core_vars(ngx_conf_t *cf) return NGX_ERROR; } + if (ngx_array_init(&cmcf->prefix_variables, cf->pool, 8, + sizeof(ngx_stream_variable_t)) + != NGX_OK) + { + return NGX_ERROR; + } + for (cv = ngx_stream_core_variables; cv->name.len; cv++) { - v = ngx_palloc(cf->pool, sizeof(ngx_stream_variable_t)); + v = ngx_stream_add_variable(cf, &cv->name, cv->flags); if (v == NULL) { return NGX_ERROR; } *v = *cv; - - rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, - NGX_HASH_READONLY_KEY); - - if (rc == NGX_OK) { - continue; - } - - if (rc == NGX_BUSY) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "conflicting variable name \"%V\"", &v->name); - } - - return NGX_ERROR; } return NGX_OK; @@ -1051,10 +1129,11 @@ ngx_stream_variables_add_core_vars(ngx_conf_t *cf) ngx_int_t ngx_stream_variables_init_vars(ngx_conf_t *cf) { + size_t len; ngx_uint_t i, n; ngx_hash_key_t *key; ngx_hash_init_t hash; - ngx_stream_variable_t *v, *av; + ngx_stream_variable_t *v, *av, *pv; ngx_stream_core_main_conf_t *cmcf; /* set the handlers for the indexed stream variables */ @@ -1062,6 +1141,7 @@ ngx_stream_variables_init_vars(ngx_conf_t *cf) cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); v = cmcf->variables.elts; + pv = cmcf->prefix_variables.elts; key = cmcf->variables_keys->keys.elts; for (i = 0; i < cmcf->variables.nelts; i++) { @@ -1082,7 +1162,9 @@ ngx_stream_variables_init_vars(ngx_conf_t *cf) av->index = i; - if (av->get_handler == NULL) { + if (av->get_handler == NULL + || (av->flags & NGX_STREAM_VAR_WEAK)) + { break; } @@ -1090,10 +1172,32 @@ ngx_stream_variables_init_vars(ngx_conf_t *cf) } } - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "unknown \"%V\" variable", &v[i].name); + len = 0; + av = NULL; - return NGX_ERROR; + for (n = 0; n < cmcf->prefix_variables.nelts; n++) { + if (v[i].name.len >= pv[n].name.len && v[i].name.len > len + && ngx_strncmp(v[i].name.data, pv[n].name.data, pv[n].name.len) + == 0) + { + av = &pv[n]; + len = pv[n].name.len; + } + } + + if (av) { + v[i].get_handler = av->get_handler; + v[i].data = (uintptr_t) &v[i].name; + v[i].flags = av->flags; + + goto next; + } + + if (v[i].get_handler == NULL) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "unknown \"%V\" variable", &v[i].name); + return NGX_ERROR; + } next: continue; |