Mercurial > hg > nginx
diff src/stream/ngx_stream_variables.c @ 6899:d2b2ff157da5
Variables: generic prefix variables.
author | Dmitry Volyntsev <xeioex@nginx.com> |
---|---|
date | Tue, 31 Jan 2017 21:19:58 +0300 |
parents | 8cd97c14b0e2 |
children | 2a288909abc6 0800444254e8 |
line wrap: on
line diff
--- 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, 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, return NULL; } + v->flags &= flags | ~NGX_STREAM_VAR_WEAK; + return v; } @@ -193,6 +201,60 @@ ngx_stream_add_variable(ngx_conf_t *cf, } +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_sessi 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 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_c 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_c 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_ 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_ 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_ } } - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "unknown \"%V\" variable", &v[i].name); + len = 0; + av = NULL; + + 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; + } + } - return NGX_ERROR; + 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;