comparison src/http/ngx_http_variables.c @ 50:72eb30262aac NGINX_0_1_25

nginx 0.1.25 *) Bugfix: nginx did run on Linux parisc. *) Feature: nginx now does not start under FreeBSD if the sysctl kern.ipc.somaxconn value is too big. *) Bugfix: if a request was internally redirected by the ngx_http_index_module module to the ngx_http_proxy_module or ngx_http_fastcgi_module modules, then the index file was not closed after request completion. *) Feature: the "proxy_pass" can be used in location with regular expression. *) Feature: the ngx_http_rewrite_filter_module module supports the condition like "if ($HTTP_USER_AGENT ~ MSIE)". *) Bugfix: nginx started too slow if the large number of addresses and text values were used in the "geo" directive. *) Change: a variable name must be declared as "$name" in the "geo" directive. The previous variant without "$" is still supported, but will be removed soon. *) Feature: the "%{VARIABLE}v" logging parameter. *) Feature: the "set $name value" directive. *) Bugfix: gcc 4.0 compatibility. *) Feature: the --with-openssl-opt=OPTIONS autoconfiguration directive.
author Igor Sysoev <http://sysoev.ru>
date Sat, 19 Mar 2005 00:00:00 +0300
parents 6cfc63e68377
children b55cbf18157e
comparison
equal deleted inserted replaced
49:93dabbc9efb9 50:72eb30262aac
23 23
24 24
25 static ngx_http_variable_value_t * 25 static ngx_http_variable_value_t *
26 ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data); 26 ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data);
27 static ngx_http_variable_value_t * 27 static ngx_http_variable_value_t *
28 ngx_http_variable_unknown_header(ngx_http_request_t *r, ngx_str_t *var); 28 ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data);
29 static ngx_http_variable_value_t * 29 static ngx_http_variable_value_t *
30 ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data); 30 ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data);
31 static ngx_http_variable_value_t * 31 static ngx_http_variable_value_t *
32 ngx_http_variable_uri(ngx_http_request_t *r, uintptr_t data); 32 ngx_http_variable_uri(ngx_http_request_t *r, uintptr_t data);
33 static ngx_http_variable_value_t * 33 static ngx_http_variable_value_t *
67 { ngx_null_string, NULL, 0 } 67 { ngx_null_string, NULL, 0 }
68 }; 68 };
69 69
70 70
71 ngx_http_variable_t * 71 ngx_http_variable_t *
72 ngx_http_add_variable(ngx_conf_t *cf) 72 ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t set)
73 { 73 {
74 ngx_http_variable_t *var; 74 ngx_uint_t i;
75 ngx_http_variable_t *v;
75 ngx_http_core_main_conf_t *cmcf; 76 ngx_http_core_main_conf_t *cmcf;
76 77
77 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); 78 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
78 79
79 if (cmcf->variables.elts == NULL) { 80 v = cmcf->variables.elts;
81
82 if (v == NULL) {
80 if (ngx_array_init(&cmcf->variables, cf->pool, 4, 83 if (ngx_array_init(&cmcf->variables, cf->pool, 4,
81 sizeof(ngx_http_variable_t)) == NGX_ERROR) 84 sizeof(ngx_http_variable_t)) == NGX_ERROR)
82 { 85 {
83 return NULL; 86 return NULL;
84 } 87 }
85 } 88
86 89 } else {
87 if (!(var = ngx_array_push(&cmcf->variables))) { 90 for (i = 0; i < cmcf->variables.nelts; i++) {
88 return NULL; 91 if (name->len != v[i].name.len
89 } 92 || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0)
90 93 {
91 var->index = cmcf->variables.nelts - 1; 94 continue;
92 95 }
93 return var; 96
97 if (set && v[i].handler) {
98 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
99 "the duplicate \"%V\" variable", name);
100 return NULL;
101 }
102
103 return &v[i];
104 }
105 }
106
107 v = ngx_array_push(&cmcf->variables);
108 if (v == NULL) {
109 return NULL;
110 }
111
112 v->name.len = name->len;
113 v->name.data = ngx_palloc(cf->pool, name->len);
114 if (v->name.data == NULL) {
115 return NULL;
116 }
117
118 for (i = 0; i < name->len; i++) {
119 v->name.data[i] = ngx_toupper(name->data[i]);
120 }
121
122 v->index = cmcf->variables.nelts - 1;
123 v->handler = NULL;
124 v->data = 0;
125
126 return v;
94 } 127 }
95 128
96 129
97 ngx_http_variable_value_t * 130 ngx_http_variable_value_t *
98 ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index) 131 ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
99 { 132 {
100 ngx_http_variable_t *var; 133 ngx_http_variable_t *v;
134 ngx_http_variable_value_t *vv;
101 ngx_http_core_main_conf_t *cmcf; 135 ngx_http_core_main_conf_t *cmcf;
102
103 /* TODO: cached variables */
104 136
105 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); 137 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
106 138
107 if (cmcf->variables.elts == NULL || cmcf->variables.nelts <= index) { 139 if (cmcf->variables.elts == NULL || cmcf->variables.nelts <= index) {
108 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, 140 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
109 "unknown variable index: %d", index); 141 "unknown variable index: %d", index);
110 return NULL; 142 return NULL;
111 } 143 }
112 144
113 var = cmcf->variables.elts; 145 if (r->variables && r->variables[index]) {
114 146 return r->variables[index];
115 return var[index].handler(r, var[index].data); 147 }
116 } 148
117 149 v = cmcf->variables.elts;
118 150
119 ngx_int_t 151 vv = v[index].handler(r, v[index].data);
120 ngx_http_get_variable_index(ngx_http_core_main_conf_t *cmcf, ngx_str_t *name) 152
121 { 153 if (r->variables == NULL) {
122 ngx_uint_t i; 154 r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
123 ngx_http_variable_t *var; 155 * sizeof(ngx_http_variable_value_t *));
124 156 if (r->variables == NULL) {
125 var = cmcf->variables.elts; 157 return NULL;
126 for (i = 0; i < cmcf->variables.nelts; i++) { 158 }
127 if (var[i].name.len != name->len) { 159 }
128 continue; 160
129 } 161 r->variables[index] = vv;
130 162
131 if (ngx_strncasecmp(var[i].name.data, name->data, name->len) == 0) { 163 return vv;
132 return var[i].index;
133 }
134 }
135
136 return -1;
137 } 164 }
138 165
139 166
140 ngx_http_variable_value_t * 167 ngx_http_variable_value_t *
141 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name) 168 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name)
142 { 169 {
143 ngx_int_t index;
144 ngx_uint_t i, key; 170 ngx_uint_t i, key;
145 ngx_http_core_variable_t *var; 171 ngx_http_variable_t *v;
172 ngx_http_core_variable_t *cv;
146 ngx_http_core_main_conf_t *cmcf; 173 ngx_http_core_main_conf_t *cmcf;
147 174
148 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); 175 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
149 176
150 index = ngx_http_get_variable_index(cmcf, name); 177 v = cmcf->variables.elts;
151 178 for (i = 0; i < cmcf->variables.nelts; i++) {
152 if (index != -1) { 179 if (v[i].name.len != name->len) {
153 return ngx_http_get_indexed_variable(r, index); 180 continue;
181 }
182
183 if (ngx_strncmp(v[i].name.data, name->data, name->len) == 0) {
184 return ngx_http_get_indexed_variable(r, v[i].index);
185 }
154 } 186 }
155 187
156 ngx_http_vars_hash_key(key, name); 188 ngx_http_vars_hash_key(key, name);
157 189
158 var = ngx_http_core_variables_hash[key].elts; 190 cv = ngx_http_core_variables_hash[key].elts;
159 for (i = 0; i < ngx_http_core_variables_hash[key].nelts; i++) { 191 for (i = 0; i < ngx_http_core_variables_hash[key].nelts; i++) {
160 192 if (cv[i].name.len != name->len) {
161 if (var[i].name.len != name->len
162 || ngx_strncasecmp(var[i].name.data, name->data, name->len) != 0)
163 {
164 continue; 193 continue;
165 } 194 }
166 195
167 return var[i].handler(r, var[i].data); 196 if (ngx_strncmp(cv[i].name.data, name->data, name->len) == 0) {
168 } 197 return cv[i].handler(r, cv[i].data);
169 198 }
170 if (ngx_strncasecmp(name->data, "HTTP_", 5) != 0) { 199 }
171 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 200
172 "unknown \"%V\" variable", name); 201 if (ngx_strncmp(name->data, "HTTP_", 5) == 0) {
173 return NGX_HTTP_VARIABLE_NOT_FOUND; 202 return ngx_http_variable_unknown_header(r, (uintptr_t) name);
174 } 203 }
175 204
176 return ngx_http_variable_unknown_header(r, name); 205 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
206 "unknown \"%V\" variable", name);
207
208 return NGX_HTTP_VARIABLE_NOT_FOUND;
177 } 209 }
178 210
179 211
180 static ngx_http_variable_value_t * 212 static ngx_http_variable_value_t *
181 ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data) 213 ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data)
182 { 214 {
183 ngx_table_elt_t *h; 215 ngx_table_elt_t *h;
184 ngx_http_variable_value_t *v; 216 ngx_http_variable_value_t *vv;
185 217
186 h = *(ngx_table_elt_t **) ((char *) &r->headers_in + data); 218 h = *(ngx_table_elt_t **) ((char *) &r->headers_in + data);
187 219
188 if (h == NULL) { 220 if (h == NULL) {
189 return NGX_HTTP_VARIABLE_NOT_FOUND; 221 return NGX_HTTP_VARIABLE_NOT_FOUND;
190 } 222 }
191 223
192 if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) { 224 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
193 return NULL; 225 if (vv == NULL) {
194 } 226 return NULL;
195 227 }
196 v->value = 0; 228
197 v->text = h->value; 229 vv->value = 0;
198 230 vv->text = h->value;
199 return v; 231
200 } 232 return vv;
201 233 }
202 234
203 static ngx_http_variable_value_t * 235
204 ngx_http_variable_unknown_header(ngx_http_request_t *r, ngx_str_t *var) 236 static ngx_http_variable_value_t *
205 { 237 ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data)
238 {
239 ngx_str_t *var = (ngx_str_t *) data;
240
206 u_char ch; 241 u_char ch;
207 ngx_uint_t i, n; 242 ngx_uint_t i, n;
208 ngx_list_part_t *part; 243 ngx_list_part_t *part;
209 ngx_table_elt_t *header; 244 ngx_table_elt_t *header;
210 ngx_http_variable_value_t *v; 245 ngx_http_variable_value_t *vv;
211 246
212 part = &r->headers_in.headers.part; 247 part = &r->headers_in.headers.part;
213 header = part->elts; 248 header = part->elts;
214 249
215 for (i = 0; /* void */ ; i++) { 250 for (i = 0; /* void */ ; i++) {
239 break; 274 break;
240 } 275 }
241 } 276 }
242 277
243 if (n + 5 == var->len) { 278 if (n + 5 == var->len) {
244 if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) { 279 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
280 if (vv == NULL) {
245 return NULL; 281 return NULL;
246 } 282 }
247 283
248 v->value = 0; 284 vv->value = 0;
249 v->text = header[i].value; 285 vv->text = header[i].value;
250 return v; 286 return vv;
251 } 287 }
252 } 288 }
253 289
254 return NGX_HTTP_VARIABLE_NOT_FOUND; 290 return NGX_HTTP_VARIABLE_NOT_FOUND;
255 } 291 }
256 292
257 293
258 static ngx_http_variable_value_t * 294 static ngx_http_variable_value_t *
259 ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data) 295 ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data)
260 { 296 {
261 ngx_http_variable_value_t *v; 297 ngx_http_variable_value_t *vv;
262 298
263 if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) { 299 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
264 return NULL; 300 if (vv == NULL) {
265 } 301 return NULL;
266 302 }
267 v->value = 0; 303
268 v->text = r->connection->addr_text; 304 vv->value = 0;
269 305 vv->text = r->connection->addr_text;
270 return v; 306
307 return vv;
271 } 308 }
272 309
273 310
274 static ngx_http_variable_value_t * 311 static ngx_http_variable_value_t *
275 ngx_http_variable_uri(ngx_http_request_t *r, uintptr_t data) 312 ngx_http_variable_uri(ngx_http_request_t *r, uintptr_t data)
276 { 313 {
277 ngx_http_variable_value_t *v; 314 ngx_http_variable_value_t *vv;
278 315
279 if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) { 316 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
280 return NULL; 317 if (vv == NULL) {
281 } 318 return NULL;
282 319 }
283 v->value = 0; 320
284 v->text = r->uri; 321 vv->value = 0;
285 322 vv->text = r->uri;
286 return v; 323
324 return vv;
287 } 325 }
288 326
289 327
290 static ngx_http_variable_value_t * 328 static ngx_http_variable_value_t *
291 ngx_http_variable_query_string(ngx_http_request_t *r, uintptr_t data) 329 ngx_http_variable_query_string(ngx_http_request_t *r, uintptr_t data)
292 { 330 {
293 ngx_http_variable_value_t *v; 331 ngx_http_variable_value_t *vv;
294 332
295 if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) { 333 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
296 return NULL; 334 if (vv == NULL) {
297 } 335 return NULL;
298 336 }
299 v->value = 0; 337
300 v->text = r->args; 338 vv->value = 0;
301 339 vv->text = r->args;
302 return v; 340
341 return vv;
303 } 342 }
304 343
305 344
306 ngx_int_t 345 ngx_int_t
307 ngx_http_core_variables_init(ngx_cycle_t *cycle) 346 ngx_http_variables_init(ngx_cycle_t *cycle)
308 { 347 {
309 ngx_uint_t i, key; 348 ngx_uint_t i, j, key;
310 ngx_http_core_variable_t *var, *v; 349 ngx_http_variable_t *v;
350 ngx_http_core_variable_t *cv, *vp;
351 ngx_http_core_main_conf_t *cmcf;
311 352
312 ngx_http_core_variables_hash = ngx_palloc(cycle->pool, 353 ngx_http_core_variables_hash = ngx_palloc(cycle->pool,
313 NGX_HTTP_VARS_HASH_PRIME 354 NGX_HTTP_VARS_HASH_PRIME
314 * sizeof(ngx_array_t)); 355 * sizeof(ngx_array_t));
315 if (ngx_http_core_variables_hash == NULL) { 356 if (ngx_http_core_variables_hash == NULL) {
322 { 363 {
323 return NGX_ERROR; 364 return NGX_ERROR;
324 } 365 }
325 } 366 }
326 367
327 for (var = ngx_http_core_variables; var->name.len; var++) { 368 for (cv = ngx_http_core_variables; cv->name.len; cv++) {
328 ngx_http_vars_hash_key(key, &var->name); 369 ngx_http_vars_hash_key(key, &cv->name);
329 370
330 if (!(v = ngx_array_push(&ngx_http_core_variables_hash[key]))) { 371 vp = ngx_array_push(&ngx_http_core_variables_hash[key]);
372 if (vp == NULL) {
331 return NGX_ERROR; 373 return NGX_ERROR;
332 } 374 }
333 375
334 *v = *var; 376 *vp = *cv;
377 }
378
379
380 cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
381
382 v = cmcf->variables.elts;
383 for (i = 0; i < cmcf->variables.nelts; i++) {
384
385 if (v[i].handler) {
386 continue;
387 }
388
389 ngx_http_vars_hash_key(key, &v[i].name);
390
391 cv = ngx_http_core_variables_hash[key].elts;
392 for (j = 0; j < ngx_http_core_variables_hash[key].nelts; j++) {
393 if (cv[j].name.len != v[i].name.len) {
394 continue;
395 }
396
397 if (ngx_strncmp(cv[j].name.data, v[i].name.data, v[i].name.len)
398 == 0)
399 {
400 v[i].handler = cv[j].handler;
401 v[i].data = cv[j].data;
402 continue;
403 }
404 }
405
406 if (ngx_strncmp(v[i].name.data, "HTTP_", 5) == 0) {
407 v[i].handler = ngx_http_variable_unknown_header;
408 v[i].data = (uintptr_t) &v[i].name;
409 continue;
410 }
411
412 ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
413 "unknown \"%V\" variable", &v[i].name);
414
415 return NGX_ERROR;
335 } 416 }
336 417
337 return NGX_OK; 418 return NGX_OK;
338 } 419 }