Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/http/ngx_http_variables.c')
-rw-r--r--src/http/ngx_http_variables.c235
1 files changed, 158 insertions, 77 deletions
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index e65f38858..154ee1352 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -25,7 +25,7 @@
static ngx_http_variable_value_t *
ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data);
static ngx_http_variable_value_t *
- ngx_http_variable_unknown_header(ngx_http_request_t *r, ngx_str_t *var);
+ ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data);
static ngx_http_variable_value_t *
ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data);
static ngx_http_variable_value_t *
@@ -69,39 +69,71 @@ static ngx_http_core_variable_t ngx_http_core_variables[] = {
ngx_http_variable_t *
-ngx_http_add_variable(ngx_conf_t *cf)
+ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t set)
{
- ngx_http_variable_t *var;
+ ngx_uint_t i;
+ ngx_http_variable_t *v;
ngx_http_core_main_conf_t *cmcf;
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
- if (cmcf->variables.elts == NULL) {
+ v = cmcf->variables.elts;
+
+ if (v == NULL) {
if (ngx_array_init(&cmcf->variables, cf->pool, 4,
sizeof(ngx_http_variable_t)) == NGX_ERROR)
{
return NULL;
}
+
+ } else {
+ for (i = 0; i < cmcf->variables.nelts; i++) {
+ if (name->len != v[i].name.len
+ || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0)
+ {
+ continue;
+ }
+
+ if (set && v[i].handler) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the duplicate \"%V\" variable", name);
+ return NULL;
+ }
+
+ return &v[i];
+ }
}
- if (!(var = ngx_array_push(&cmcf->variables))) {
+ v = ngx_array_push(&cmcf->variables);
+ if (v == NULL) {
return NULL;
}
- var->index = cmcf->variables.nelts - 1;
+ v->name.len = name->len;
+ v->name.data = ngx_palloc(cf->pool, name->len);
+ if (v->name.data == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < name->len; i++) {
+ v->name.data[i] = ngx_toupper(name->data[i]);
+ }
- return var;
+ v->index = cmcf->variables.nelts - 1;
+ v->handler = NULL;
+ v->data = 0;
+
+ return v;
}
ngx_http_variable_value_t *
ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
{
- ngx_http_variable_t *var;
+ ngx_http_variable_t *v;
+ ngx_http_variable_value_t *vv;
ngx_http_core_main_conf_t *cmcf;
- /* TODO: cached variables */
-
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
if (cmcf->variables.elts == NULL || cmcf->variables.nelts <= index) {
@@ -110,70 +142,70 @@ ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
return NULL;
}
- var = cmcf->variables.elts;
-
- return var[index].handler(r, var[index].data);
-}
-
+ if (r->variables && r->variables[index]) {
+ return r->variables[index];
+ }
-ngx_int_t
-ngx_http_get_variable_index(ngx_http_core_main_conf_t *cmcf, ngx_str_t *name)
-{
- ngx_uint_t i;
- ngx_http_variable_t *var;
+ v = cmcf->variables.elts;
- var = cmcf->variables.elts;
- for (i = 0; i < cmcf->variables.nelts; i++) {
- if (var[i].name.len != name->len) {
- continue;
- }
+ vv = v[index].handler(r, v[index].data);
- if (ngx_strncasecmp(var[i].name.data, name->data, name->len) == 0) {
- return var[i].index;
+ if (r->variables == NULL) {
+ r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
+ * sizeof(ngx_http_variable_value_t *));
+ if (r->variables == NULL) {
+ return NULL;
}
}
- return -1;
+ r->variables[index] = vv;
+
+ return vv;
}
ngx_http_variable_value_t *
ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name)
{
- ngx_int_t index;
ngx_uint_t i, key;
- ngx_http_core_variable_t *var;
+ ngx_http_variable_t *v;
+ ngx_http_core_variable_t *cv;
ngx_http_core_main_conf_t *cmcf;
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
- index = ngx_http_get_variable_index(cmcf, name);
+ v = cmcf->variables.elts;
+ for (i = 0; i < cmcf->variables.nelts; i++) {
+ if (v[i].name.len != name->len) {
+ continue;
+ }
- if (index != -1) {
- return ngx_http_get_indexed_variable(r, index);
+ if (ngx_strncmp(v[i].name.data, name->data, name->len) == 0) {
+ return ngx_http_get_indexed_variable(r, v[i].index);
+ }
}
ngx_http_vars_hash_key(key, name);
- var = ngx_http_core_variables_hash[key].elts;
+ cv = ngx_http_core_variables_hash[key].elts;
for (i = 0; i < ngx_http_core_variables_hash[key].nelts; i++) {
-
- if (var[i].name.len != name->len
- || ngx_strncasecmp(var[i].name.data, name->data, name->len) != 0)
- {
+ if (cv[i].name.len != name->len) {
continue;
}
- return var[i].handler(r, var[i].data);
+ if (ngx_strncmp(cv[i].name.data, name->data, name->len) == 0) {
+ return cv[i].handler(r, cv[i].data);
+ }
}
- if (ngx_strncasecmp(name->data, "HTTP_", 5) != 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "unknown \"%V\" variable", name);
- return NGX_HTTP_VARIABLE_NOT_FOUND;
+ if (ngx_strncmp(name->data, "HTTP_", 5) == 0) {
+ return ngx_http_variable_unknown_header(r, (uintptr_t) name);
}
- return ngx_http_variable_unknown_header(r, name);
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "unknown \"%V\" variable", name);
+
+ return NGX_HTTP_VARIABLE_NOT_FOUND;
}
@@ -181,7 +213,7 @@ static ngx_http_variable_value_t *
ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data)
{
ngx_table_elt_t *h;
- ngx_http_variable_value_t *v;
+ ngx_http_variable_value_t *vv;
h = *(ngx_table_elt_t **) ((char *) &r->headers_in + data);
@@ -189,25 +221,28 @@ ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data)
return NGX_HTTP_VARIABLE_NOT_FOUND;
}
- if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) {
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
return NULL;
}
- v->value = 0;
- v->text = h->value;
+ vv->value = 0;
+ vv->text = h->value;
- return v;
+ return vv;
}
static ngx_http_variable_value_t *
-ngx_http_variable_unknown_header(ngx_http_request_t *r, ngx_str_t *var)
+ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data)
{
+ ngx_str_t *var = (ngx_str_t *) data;
+
u_char ch;
ngx_uint_t i, n;
ngx_list_part_t *part;
ngx_table_elt_t *header;
- ngx_http_variable_value_t *v;
+ ngx_http_variable_value_t *vv;
part = &r->headers_in.headers.part;
header = part->elts;
@@ -241,13 +276,14 @@ ngx_http_variable_unknown_header(ngx_http_request_t *r, ngx_str_t *var)
}
if (n + 5 == var->len) {
- if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) {
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
return NULL;
}
- v->value = 0;
- v->text = header[i].value;
- return v;
+ vv->value = 0;
+ vv->text = header[i].value;
+ return vv;
}
}
@@ -258,56 +294,61 @@ ngx_http_variable_unknown_header(ngx_http_request_t *r, ngx_str_t *var)
static ngx_http_variable_value_t *
ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data)
{
- ngx_http_variable_value_t *v;
+ ngx_http_variable_value_t *vv;
- if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) {
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
return NULL;
}
- v->value = 0;
- v->text = r->connection->addr_text;
+ vv->value = 0;
+ vv->text = r->connection->addr_text;
- return v;
+ return vv;
}
static ngx_http_variable_value_t *
ngx_http_variable_uri(ngx_http_request_t *r, uintptr_t data)
{
- ngx_http_variable_value_t *v;
+ ngx_http_variable_value_t *vv;
- if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) {
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
return NULL;
}
- v->value = 0;
- v->text = r->uri;
+ vv->value = 0;
+ vv->text = r->uri;
- return v;
+ return vv;
}
static ngx_http_variable_value_t *
ngx_http_variable_query_string(ngx_http_request_t *r, uintptr_t data)
{
- ngx_http_variable_value_t *v;
+ ngx_http_variable_value_t *vv;
- if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) {
+ vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+ if (vv == NULL) {
return NULL;
}
- v->value = 0;
- v->text = r->args;
+ vv->value = 0;
+ vv->text = r->args;
- return v;
+ return vv;
}
ngx_int_t
-ngx_http_core_variables_init(ngx_cycle_t *cycle)
+ngx_http_variables_init(ngx_cycle_t *cycle)
{
- ngx_uint_t i, key;
- ngx_http_core_variable_t *var, *v;
+ ngx_uint_t i, j, key;
+ ngx_http_variable_t *v;
+ ngx_http_core_variable_t *cv, *vp;
+ ngx_http_core_main_conf_t *cmcf;
ngx_http_core_variables_hash = ngx_palloc(cycle->pool,
NGX_HTTP_VARS_HASH_PRIME
@@ -324,14 +365,54 @@ ngx_http_core_variables_init(ngx_cycle_t *cycle)
}
}
- for (var = ngx_http_core_variables; var->name.len; var++) {
- ngx_http_vars_hash_key(key, &var->name);
+ for (cv = ngx_http_core_variables; cv->name.len; cv++) {
+ ngx_http_vars_hash_key(key, &cv->name);
- if (!(v = ngx_array_push(&ngx_http_core_variables_hash[key]))) {
+ vp = ngx_array_push(&ngx_http_core_variables_hash[key]);
+ if (vp == NULL) {
return NGX_ERROR;
}
- *v = *var;
+ *vp = *cv;
+ }
+
+
+ cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
+
+ v = cmcf->variables.elts;
+ for (i = 0; i < cmcf->variables.nelts; i++) {
+
+ if (v[i].handler) {
+ continue;
+ }
+
+ ngx_http_vars_hash_key(key, &v[i].name);
+
+ cv = ngx_http_core_variables_hash[key].elts;
+ for (j = 0; j < ngx_http_core_variables_hash[key].nelts; j++) {
+ if (cv[j].name.len != v[i].name.len) {
+ continue;
+ }
+
+ if (ngx_strncmp(cv[j].name.data, v[i].name.data, v[i].name.len)
+ == 0)
+ {
+ v[i].handler = cv[j].handler;
+ v[i].data = cv[j].data;
+ continue;
+ }
+ }
+
+ if (ngx_strncmp(v[i].name.data, "HTTP_", 5) == 0) {
+ v[i].handler = ngx_http_variable_unknown_header;
+ v[i].data = (uintptr_t) &v[i].name;
+ continue;
+ }
+
+ ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
+ "unknown \"%V\" variable", &v[i].name);
+
+ return NGX_ERROR;
}
return NGX_OK;