Mercurial > hg > nginx
annotate src/http/ngx_http_variables.c @ 9230:e14debe728b0 radix_with_skip
Closed the radix_with_skip branch.
The radix_with_skip branch is an archive of an experiment did in 2008,
and it is no longer relevant. It is now closed to avoid cluttering of
the branches list. If needed, closed branches still can be seen with
"hg branches --closed".
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sat, 23 Mar 2024 04:30:45 +0300 |
parents | 4fee4ebbfb0b |
children | d311b7f6a403 |
rev | line source |
---|---|
499 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
1329 | 10 #include <nginx.h> |
499 | 11 |
12 | |
573 | 13 static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r, |
14 ngx_http_variable_value_t *v, uintptr_t data); | |
1350 | 15 static void ngx_http_variable_request_set(ngx_http_request_t *r, |
16 ngx_http_variable_value_t *v, uintptr_t data); | |
637 | 17 static void ngx_http_variable_request_set_size(ngx_http_request_t *r, |
18 ngx_http_variable_value_t *v, uintptr_t data); | |
573 | 19 static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r, |
20 ngx_http_variable_value_t *v, uintptr_t data); | |
21 static ngx_int_t ngx_http_variable_headers(ngx_http_request_t *r, | |
22 ngx_http_variable_value_t *v, uintptr_t data); | |
577 | 23 |
24 static ngx_int_t ngx_http_variable_unknown_header_in(ngx_http_request_t *r, | |
573 | 25 ngx_http_variable_value_t *v, uintptr_t data); |
577 | 26 static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r, |
27 ngx_http_variable_value_t *v, uintptr_t data); | |
2359
4fee4ebbfb0b
$cookie_... variable did not for SSI and perl
Igor Sysoev <igor@sysoev.ru>
parents:
2333
diff
changeset
|
28 static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r, |
4fee4ebbfb0b
$cookie_... variable did not for SSI and perl
Igor Sysoev <igor@sysoev.ru>
parents:
2333
diff
changeset
|
29 ngx_http_variable_value_t *v, uintptr_t data); |
2137 | 30 static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, |
31 ngx_http_variable_value_t *v, uintptr_t data); | |
577 | 32 |
573 | 33 static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r, |
34 ngx_http_variable_value_t *v, uintptr_t data); | |
983
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
35 static ngx_int_t ngx_http_variable_binary_remote_addr(ngx_http_request_t *r, |
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
36 ngx_http_variable_value_t *v, uintptr_t data); |
573 | 37 static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r, |
38 ngx_http_variable_value_t *v, uintptr_t data); | |
39 static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r, | |
40 ngx_http_variable_value_t *v, uintptr_t data); | |
41 static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r, | |
42 ngx_http_variable_value_t *v, uintptr_t data); | |
43 static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r, | |
44 ngx_http_variable_value_t *v, uintptr_t data); | |
731 | 45 static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r, |
46 ngx_http_variable_value_t *v, uintptr_t data); | |
1351 | 47 static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r, |
48 ngx_http_variable_value_t *v, uintptr_t data); | |
573 | 49 static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r, |
50 ngx_http_variable_value_t *v, uintptr_t data); | |
2259 | 51 static ngx_int_t ngx_http_variable_realpath_root(ngx_http_request_t *r, |
52 ngx_http_variable_value_t *v, uintptr_t data); | |
573 | 53 static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r, |
54 ngx_http_variable_value_t *v, uintptr_t data); | |
1811 | 55 static ngx_int_t ngx_http_variable_server_name(ngx_http_request_t *r, |
56 ngx_http_variable_value_t *v, uintptr_t data); | |
573 | 57 static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r, |
58 ngx_http_variable_value_t *v, uintptr_t data); | |
59 static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r, | |
60 ngx_http_variable_value_t *v, uintptr_t data); | |
611 | 61 static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r, |
62 ngx_http_variable_value_t *v, uintptr_t data); | |
629 | 63 static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r, |
64 ngx_http_variable_value_t *v, uintptr_t data); | |
759 | 65 static ngx_int_t ngx_http_variable_request_body_file(ngx_http_request_t *r, |
66 ngx_http_variable_value_t *v, uintptr_t data); | |
499 | 67 |
641 | 68 static ngx_int_t ngx_http_variable_sent_content_type(ngx_http_request_t *r, |
69 ngx_http_variable_value_t *v, uintptr_t data); | |
70 static ngx_int_t ngx_http_variable_sent_content_length(ngx_http_request_t *r, | |
71 ngx_http_variable_value_t *v, uintptr_t data); | |
72 static ngx_int_t ngx_http_variable_sent_last_modified(ngx_http_request_t *r, | |
73 ngx_http_variable_value_t *v, uintptr_t data); | |
74 static ngx_int_t ngx_http_variable_sent_connection(ngx_http_request_t *r, | |
75 ngx_http_variable_value_t *v, uintptr_t data); | |
76 static ngx_int_t ngx_http_variable_sent_keep_alive(ngx_http_request_t *r, | |
77 ngx_http_variable_value_t *v, uintptr_t data); | |
78 static ngx_int_t ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r, | |
79 ngx_http_variable_value_t *v, uintptr_t data); | |
80 | |
1329 | 81 static ngx_int_t ngx_http_variable_nginx_version(ngx_http_request_t *r, |
82 ngx_http_variable_value_t *v, uintptr_t data); | |
2011 | 83 static ngx_int_t ngx_http_variable_hostname(ngx_http_request_t *r, |
84 ngx_http_variable_value_t *v, uintptr_t data); | |
2249 | 85 static ngx_int_t ngx_http_variable_pid(ngx_http_request_t *r, |
86 ngx_http_variable_value_t *v, uintptr_t data); | |
499 | 87 |
509 | 88 /* |
89 * TODO: | |
90 * Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED | |
91 * REMOTE_HOST (null), REMOTE_IDENT (null), | |
92 * SERVER_SOFTWARE | |
93 * | |
571 | 94 * Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner) |
509 | 95 */ |
499 | 96 |
641 | 97 /* |
98 * the $http_host, $http_user_agent, $http_referer, $http_via, | |
99 * and $http_x_forwarded_for variables may be handled by generic | |
100 * ngx_http_variable_unknown_header_in(), but for perfomance reasons | |
101 * they are handled using dedicated entries | |
102 */ | |
103 | |
509 | 104 static ngx_http_variable_t ngx_http_core_variables[] = { |
105 | |
637 | 106 { ngx_string("http_host"), NULL, ngx_http_variable_header, |
533 | 107 offsetof(ngx_http_request_t, headers_in.host), 0, 0 }, |
499 | 108 |
637 | 109 { ngx_string("http_user_agent"), NULL, ngx_http_variable_header, |
533 | 110 offsetof(ngx_http_request_t, headers_in.user_agent), 0, 0 }, |
509 | 111 |
637 | 112 { ngx_string("http_referer"), NULL, ngx_http_variable_header, |
533 | 113 offsetof(ngx_http_request_t, headers_in.referer), 0, 0 }, |
499 | 114 |
115 #if (NGX_HTTP_GZIP) | |
637 | 116 { ngx_string("http_via"), NULL, ngx_http_variable_header, |
533 | 117 offsetof(ngx_http_request_t, headers_in.via), 0, 0 }, |
499 | 118 #endif |
119 | |
1113
f1d7cf0f68e3
optimize $http_x_forwarded_for
Igor Sysoev <igor@sysoev.ru>
parents:
983
diff
changeset
|
120 #if (NGX_HTTP_PROXY || NGX_HTTP_REALIP) |
637 | 121 { ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_header, |
533 | 122 offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 }, |
499 | 123 #endif |
124 | |
637 | 125 { ngx_string("http_cookie"), NULL, ngx_http_variable_headers, |
533 | 126 offsetof(ngx_http_request_t, headers_in.cookies), 0, 0 }, |
515 | 127 |
637 | 128 { ngx_string("content_length"), NULL, ngx_http_variable_header, |
533 | 129 offsetof(ngx_http_request_t, headers_in.content_length), 0, 0 }, |
509 | 130 |
637 | 131 { ngx_string("content_type"), NULL, ngx_http_variable_header, |
533 | 132 offsetof(ngx_http_request_t, headers_in.content_type), 0, 0 }, |
509 | 133 |
637 | 134 { ngx_string("host"), NULL, ngx_http_variable_host, 0, 0, 0 }, |
509 | 135 |
982 | 136 { ngx_string("binary_remote_addr"), NULL, |
983
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
137 ngx_http_variable_binary_remote_addr, 0, 0, 0 }, |
982 | 138 |
637 | 139 { ngx_string("remote_addr"), NULL, ngx_http_variable_remote_addr, 0, 0, 0 }, |
499 | 140 |
637 | 141 { ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 }, |
509 | 142 |
637 | 143 { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 }, |
509 | 144 |
637 | 145 { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 }, |
509 | 146 |
637 | 147 { ngx_string("server_protocol"), NULL, ngx_http_variable_request, |
533 | 148 offsetof(ngx_http_request_t, http_protocol), 0, 0 }, |
509 | 149 |
731 | 150 { ngx_string("scheme"), NULL, ngx_http_variable_scheme, 0, 0, 0 }, |
151 | |
637 | 152 { ngx_string("request_uri"), NULL, ngx_http_variable_request, |
533 | 153 offsetof(ngx_http_request_t, unparsed_uri), 0, 0 }, |
499 | 154 |
637 | 155 { ngx_string("uri"), NULL, ngx_http_variable_request, |
156 offsetof(ngx_http_request_t, uri), | |
1565 | 157 NGX_HTTP_VAR_NOCACHEABLE, 0 }, |
637 | 158 |
159 { ngx_string("document_uri"), NULL, ngx_http_variable_request, | |
573 | 160 offsetof(ngx_http_request_t, uri), |
1565 | 161 NGX_HTTP_VAR_NOCACHEABLE, 0 }, |
573 | 162 |
637 | 163 { ngx_string("request"), NULL, ngx_http_variable_request, |
569 | 164 offsetof(ngx_http_request_t, request_line), 0, 0 }, |
165 | |
637 | 166 { ngx_string("document_root"), NULL, |
1565 | 167 ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, |
509 | 168 |
2259 | 169 { ngx_string("realpath_root"), NULL, |
170 ngx_http_variable_realpath_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, | |
171 | |
637 | 172 { ngx_string("query_string"), NULL, ngx_http_variable_request, |
509 | 173 offsetof(ngx_http_request_t, args), |
1565 | 174 NGX_HTTP_VAR_NOCACHEABLE, 0 }, |
499 | 175 |
1350 | 176 { ngx_string("args"), |
177 ngx_http_variable_request_set, | |
178 ngx_http_variable_request, | |
589 | 179 offsetof(ngx_http_request_t, args), |
1565 | 180 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, |
589 | 181 |
1351 | 182 { ngx_string("is_args"), NULL, ngx_http_variable_is_args, |
1565 | 183 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, |
1351 | 184 |
637 | 185 { ngx_string("request_filename"), NULL, |
186 ngx_http_variable_request_filename, 0, | |
1565 | 187 NGX_HTTP_VAR_NOCACHEABLE, 0 }, |
509 | 188 |
1811 | 189 { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 }, |
509 | 190 |
637 | 191 { ngx_string("request_method"), NULL, |
192 ngx_http_variable_request_method, 0, 0, 0 }, | |
509 | 193 |
637 | 194 { ngx_string("remote_user"), NULL, ngx_http_variable_remote_user, 0, 0, 0 }, |
509 | 195 |
637 | 196 { ngx_string("body_bytes_sent"), NULL, ngx_http_variable_body_bytes_sent, |
611 | 197 0, 0, 0 }, |
198 | |
637 | 199 { ngx_string("request_completion"), NULL, |
200 ngx_http_variable_request_completion, | |
629 | 201 0, 0, 0 }, |
202 | |
759 | 203 { ngx_string("request_body_file"), NULL, |
204 ngx_http_variable_request_body_file, | |
205 0, 0, 0 }, | |
206 | |
641 | 207 { ngx_string("sent_http_content_type"), NULL, |
208 ngx_http_variable_sent_content_type, 0, 0, 0 }, | |
209 | |
210 { ngx_string("sent_http_content_length"), NULL, | |
211 ngx_http_variable_sent_content_length, 0, 0, 0 }, | |
212 | |
213 { ngx_string("sent_http_last_modified"), NULL, | |
214 ngx_http_variable_sent_last_modified, 0, 0, 0 }, | |
215 | |
216 { ngx_string("sent_http_connection"), NULL, | |
217 ngx_http_variable_sent_connection, 0, 0, 0 }, | |
218 | |
219 { ngx_string("sent_http_keep_alive"), NULL, | |
220 ngx_http_variable_sent_keep_alive, 0, 0, 0 }, | |
221 | |
222 { ngx_string("sent_http_transfer_encoding"), NULL, | |
223 ngx_http_variable_sent_transfer_encoding, 0, 0, 0 }, | |
224 | |
225 { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers, | |
226 offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 }, | |
227 | |
637 | 228 { ngx_string("limit_rate"), ngx_http_variable_request_set_size, |
229 ngx_http_variable_request, | |
230 offsetof(ngx_http_request_t, limit_rate), | |
1565 | 231 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 }, |
637 | 232 |
1329 | 233 { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version, |
234 0, 0, 0 }, | |
235 | |
2011 | 236 { ngx_string("hostname"), NULL, ngx_http_variable_hostname, |
237 0, 0, 0 }, | |
238 | |
2249 | 239 { ngx_string("pid"), NULL, ngx_http_variable_pid, |
240 0, 0, 0 }, | |
241 | |
637 | 242 { ngx_null_string, NULL, NULL, 0, 0, 0 } |
499 | 243 }; |
244 | |
245 | |
577 | 246 ngx_http_variable_value_t ngx_http_variable_null_value = |
247 ngx_http_variable(""); | |
248 ngx_http_variable_value_t ngx_http_variable_true_value = | |
249 ngx_http_variable("1"); | |
250 | |
251 | |
499 | 252 ngx_http_variable_t * |
509 | 253 ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) |
254 { | |
611 | 255 ngx_int_t rc; |
509 | 256 ngx_uint_t i; |
611 | 257 ngx_hash_key_t *key; |
509 | 258 ngx_http_variable_t *v; |
259 ngx_http_core_main_conf_t *cmcf; | |
260 | |
261 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); | |
262 | |
611 | 263 key = cmcf->variables_keys->keys.elts; |
264 for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) { | |
265 if (name->len != key[i].key.len | |
266 || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0) | |
509 | 267 { |
268 continue; | |
269 } | |
270 | |
611 | 271 v = key[i].value; |
272 | |
1565 | 273 if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) { |
509 | 274 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
275 "the duplicate \"%V\" variable", name); | |
276 return NULL; | |
277 } | |
278 | |
611 | 279 return v; |
509 | 280 } |
281 | |
611 | 282 v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t)); |
509 | 283 if (v == NULL) { |
284 return NULL; | |
285 } | |
286 | |
287 v->name.len = name->len; | |
2049 | 288 v->name.data = ngx_pnalloc(cf->pool, name->len); |
509 | 289 if (v->name.data == NULL) { |
290 return NULL; | |
291 } | |
292 | |
2135 | 293 ngx_strlow(v->name.data, name->data, name->len); |
509 | 294 |
637 | 295 v->set_handler = NULL; |
296 v->get_handler = NULL; | |
509 | 297 v->data = 0; |
298 v->flags = flags; | |
533 | 299 v->index = 0; |
509 | 300 |
611 | 301 rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0); |
302 | |
303 if (rc == NGX_ERROR) { | |
304 return NULL; | |
305 } | |
306 | |
307 if (rc == NGX_BUSY) { | |
308 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
309 "conflicting variable name \"%V\"", name); | |
310 return NULL; | |
311 } | |
312 | |
509 | 313 return v; |
314 } | |
315 | |
316 | |
317 ngx_int_t | |
318 ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name) | |
499 | 319 { |
501 | 320 ngx_uint_t i; |
321 ngx_http_variable_t *v; | |
499 | 322 ngx_http_core_main_conf_t *cmcf; |
323 | |
324 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); | |
325 | |
501 | 326 v = cmcf->variables.elts; |
327 | |
328 if (v == NULL) { | |
499 | 329 if (ngx_array_init(&cmcf->variables, cf->pool, 4, |
330 sizeof(ngx_http_variable_t)) == NGX_ERROR) | |
331 { | |
509 | 332 return NGX_ERROR; |
499 | 333 } |
501 | 334 |
335 } else { | |
336 for (i = 0; i < cmcf->variables.nelts; i++) { | |
337 if (name->len != v[i].name.len | |
338 || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) | |
339 { | |
340 continue; | |
341 } | |
342 | |
509 | 343 return i; |
501 | 344 } |
499 | 345 } |
346 | |
501 | 347 v = ngx_array_push(&cmcf->variables); |
348 if (v == NULL) { | |
509 | 349 return NGX_ERROR; |
499 | 350 } |
351 | |
501 | 352 v->name.len = name->len; |
2049 | 353 v->name.data = ngx_pnalloc(cf->pool, name->len); |
501 | 354 if (v->name.data == NULL) { |
509 | 355 return NGX_ERROR; |
501 | 356 } |
499 | 357 |
2135 | 358 ngx_strlow(v->name.data, name->data, name->len); |
501 | 359 |
637 | 360 v->set_handler = NULL; |
361 v->get_handler = NULL; | |
501 | 362 v->data = 0; |
509 | 363 v->flags = 0; |
533 | 364 v->index = cmcf->variables.nelts - 1; |
501 | 365 |
509 | 366 return cmcf->variables.nelts - 1; |
499 | 367 } |
368 | |
369 | |
370 ngx_http_variable_value_t * | |
371 ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index) | |
372 { | |
501 | 373 ngx_http_variable_t *v; |
499 | 374 ngx_http_core_main_conf_t *cmcf; |
375 | |
376 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
377 | |
553 | 378 if (cmcf->variables.nelts <= index) { |
499 | 379 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, |
380 "unknown variable index: %d", index); | |
381 return NULL; | |
382 } | |
383 | |
573 | 384 if (r->variables[index].not_found || r->variables[index].valid) { |
385 return &r->variables[index]; | |
501 | 386 } |
499 | 387 |
501 | 388 v = cmcf->variables.elts; |
499 | 389 |
637 | 390 if (v[index].get_handler(r, &r->variables[index], v[index].data) |
391 == NGX_OK) | |
392 { | |
1565 | 393 if (v[index].flags & NGX_HTTP_VAR_NOCACHEABLE) { |
394 r->variables[index].no_cacheable = 1; | |
499 | 395 } |
573 | 396 |
397 return &r->variables[index]; | |
499 | 398 } |
399 | |
657 | 400 r->variables[index].valid = 0; |
401 r->variables[index].not_found = 1; | |
402 | |
798 | 403 return NULL; |
573 | 404 } |
405 | |
406 | |
407 ngx_http_variable_value_t * | |
408 ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index) | |
409 { | |
1150 | 410 ngx_http_variable_value_t *v; |
573 | 411 |
412 v = &r->variables[index]; | |
413 | |
414 if (v->valid) { | |
1565 | 415 if (!v->no_cacheable) { |
573 | 416 return v; |
417 } | |
418 | |
419 v->valid = 0; | |
420 v->not_found = 0; | |
509 | 421 } |
501 | 422 |
573 | 423 return ngx_http_get_indexed_variable(r, index); |
499 | 424 } |
425 | |
426 | |
427 ngx_http_variable_value_t * | |
635 | 428 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key, |
429 ngx_uint_t nowarn) | |
499 | 430 { |
501 | 431 ngx_http_variable_t *v; |
573 | 432 ngx_http_variable_value_t *vv; |
499 | 433 ngx_http_core_main_conf_t *cmcf; |
434 | |
435 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
436 | |
611 | 437 v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len); |
499 | 438 |
611 | 439 if (v) { |
440 if (v->flags & NGX_HTTP_VAR_INDEXED) { | |
441 return ngx_http_get_indexed_variable(r, v->index); | |
519 | 442 |
443 } else { | |
499 | 444 |
573 | 445 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); |
501 | 446 |
637 | 447 if (vv && v->get_handler(r, vv, v->data) == NGX_OK) { |
573 | 448 return vv; |
449 } | |
509 | 450 |
573 | 451 return NULL; |
452 } | |
509 | 453 } |
454 | |
455 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); | |
456 if (vv == NULL) { | |
457 return NULL; | |
458 } | |
459 | |
573 | 460 if (ngx_strncmp(name->data, "http_", 5) == 0) { |
499 | 461 |
577 | 462 if (ngx_http_variable_unknown_header_in(r, vv, (uintptr_t) name) |
463 == NGX_OK) | |
464 { | |
465 return vv; | |
466 } | |
467 | |
468 return NULL; | |
469 } | |
470 | |
471 if (ngx_strncmp(name->data, "sent_http_", 10) == 0) { | |
472 | |
473 if (ngx_http_variable_unknown_header_out(r, vv, (uintptr_t) name) | |
474 == NGX_OK) | |
573 | 475 { |
476 return vv; | |
477 } | |
499 | 478 |
479 return NULL; | |
480 } | |
481 | |
1162 | 482 if (ngx_strncmp(name->data, "upstream_http_", 10) == 0) { |
483 | |
484 if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name) | |
485 == NGX_OK) | |
486 { | |
487 return vv; | |
488 } | |
489 | |
490 return NULL; | |
491 } | |
492 | |
2307 | 493 if (ngx_strncmp(name->data, "cookie_", 7) == 0) { |
494 | |
2359
4fee4ebbfb0b
$cookie_... variable did not for SSI and perl
Igor Sysoev <igor@sysoev.ru>
parents:
2333
diff
changeset
|
495 if (ngx_http_variable_cookie(r, vv, (uintptr_t) name) == NGX_OK) { |
2307 | 496 return vv; |
497 } | |
498 | |
499 return NULL; | |
500 } | |
501 | |
2137 | 502 if (ngx_strncmp(name->data, "arg_", 4) == 0) { |
503 | |
504 if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) { | |
505 return vv; | |
506 } | |
507 | |
508 return NULL; | |
509 } | |
510 | |
635 | 511 vv->not_found = 1; |
573 | 512 |
635 | 513 if (nowarn == 0) { |
514 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
515 "unknown \"%V\" variable", name); | |
516 } | |
499 | 517 |
501 | 518 return vv; |
499 | 519 } |
520 | |
521 | |
573 | 522 static ngx_int_t |
523 ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v, | |
524 uintptr_t data) | |
525 { | |
526 ngx_str_t *s; | |
527 | |
528 s = (ngx_str_t *) ((char *) r + data); | |
529 | |
530 if (s->data) { | |
531 v->len = s->len; | |
532 v->valid = 1; | |
1565 | 533 v->no_cacheable = 0; |
573 | 534 v->not_found = 0; |
535 v->data = s->data; | |
536 | |
537 } else { | |
538 v->not_found = 1; | |
539 } | |
540 | |
541 return NGX_OK; | |
542 } | |
543 | |
544 | |
637 | 545 static void |
1350 | 546 ngx_http_variable_request_set(ngx_http_request_t *r, |
547 ngx_http_variable_value_t *v, uintptr_t data) | |
548 { | |
549 ngx_str_t *s; | |
550 | |
551 s = (ngx_str_t *) ((char *) r + data); | |
552 | |
553 s->len = v->len; | |
554 s->data = v->data; | |
555 } | |
556 | |
557 | |
558 static void | |
637 | 559 ngx_http_variable_request_set_size(ngx_http_request_t *r, |
560 ngx_http_variable_value_t *v, uintptr_t data) | |
561 { | |
562 ssize_t s, *sp; | |
563 ngx_str_t val; | |
564 | |
1310
33d6c994a0b2
Sun Studio on sparc uses different bit order
Igor Sysoev <igor@sysoev.ru>
parents:
1191
diff
changeset
|
565 val.len = v->len; |
637 | 566 val.data = v->data; |
567 | |
568 s = ngx_parse_size(&val); | |
569 | |
570 if (s == NGX_ERROR) { | |
571 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
572 "invalid size \"%V\"", &val); | |
573 return; | |
574 } | |
575 | |
576 sp = (ssize_t *) ((char *) r + data); | |
577 | |
578 *sp = s; | |
579 | |
580 return; | |
581 } | |
582 | |
583 | |
573 | 584 static ngx_int_t |
585 ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v, | |
586 uintptr_t data) | |
515 | 587 { |
573 | 588 ngx_table_elt_t *h; |
589 | |
590 h = *(ngx_table_elt_t **) ((char *) r + data); | |
591 | |
592 if (h) { | |
593 v->len = h->value.len; | |
594 v->valid = 1; | |
1565 | 595 v->no_cacheable = 0; |
573 | 596 v->not_found = 0; |
597 v->data = h->value.data; | |
598 | |
599 } else { | |
600 v->not_found = 1; | |
601 } | |
602 | |
603 return NGX_OK; | |
604 } | |
605 | |
606 | |
607 static ngx_int_t | |
608 ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v, | |
609 uintptr_t data) | |
610 { | |
667 | 611 ssize_t len; |
573 | 612 u_char *p; |
667 | 613 ngx_uint_t i, n; |
573 | 614 ngx_array_t *a; |
615 ngx_table_elt_t **h; | |
515 | 616 |
617 a = (ngx_array_t *) ((char *) r + data); | |
618 | |
667 | 619 n = a->nelts; |
620 | |
621 if (n == 0) { | |
573 | 622 v->not_found = 1; |
623 return NGX_OK; | |
515 | 624 } |
625 | |
573 | 626 v->valid = 1; |
1565 | 627 v->no_cacheable = 0; |
573 | 628 v->not_found = 0; |
515 | 629 |
630 h = a->elts; | |
631 | |
667 | 632 if (n == 1) { |
573 | 633 v->len = (*h)->value.len; |
634 v->data = (*h)->value.data; | |
515 | 635 |
573 | 636 return NGX_OK; |
515 | 637 } |
638 | |
667 | 639 len = - (ssize_t) (sizeof("; ") - 1); |
573 | 640 |
667 | 641 for (i = 0; i < n; i++) { |
573 | 642 len += h[i]->value.len + sizeof("; ") - 1; |
515 | 643 } |
644 | |
2049 | 645 p = ngx_pnalloc(r->pool, len); |
573 | 646 if (p == NULL) { |
647 return NGX_ERROR; | |
648 } | |
649 | |
650 v->len = len; | |
651 v->data = p; | |
515 | 652 |
653 for (i = 0; /* void */ ; i++) { | |
573 | 654 p = ngx_copy(p, h[i]->value.data, h[i]->value.len); |
515 | 655 |
667 | 656 if (i == n - 1) { |
515 | 657 break; |
658 } | |
659 | |
660 *p++ = ';'; *p++ = ' '; | |
661 } | |
662 | |
573 | 663 return NGX_OK; |
515 | 664 } |
665 | |
666 | |
573 | 667 static ngx_int_t |
577 | 668 ngx_http_variable_unknown_header_in(ngx_http_request_t *r, |
669 ngx_http_variable_value_t *v, uintptr_t data) | |
670 { | |
671 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, | |
672 &r->headers_in.headers.part, | |
673 sizeof("http_") - 1); | |
674 } | |
675 | |
676 | |
677 static ngx_int_t | |
678 ngx_http_variable_unknown_header_out(ngx_http_request_t *r, | |
573 | 679 ngx_http_variable_value_t *v, uintptr_t data) |
499 | 680 { |
577 | 681 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, |
682 &r->headers_out.headers.part, | |
683 sizeof("sent_http_") - 1); | |
684 } | |
501 | 685 |
577 | 686 |
1162 | 687 ngx_int_t |
577 | 688 ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var, |
689 ngx_list_part_t *part, size_t prefix) | |
690 { | |
573 | 691 u_char ch; |
692 ngx_uint_t i, n; | |
693 ngx_table_elt_t *header; | |
499 | 694 |
695 header = part->elts; | |
696 | |
697 for (i = 0; /* void */ ; i++) { | |
698 | |
699 if (i >= part->nelts) { | |
700 if (part->next == NULL) { | |
701 break; | |
702 } | |
703 | |
704 part = part->next; | |
705 header = part->elts; | |
706 i = 0; | |
707 } | |
708 | |
577 | 709 for (n = 0; n + prefix < var->len && n < header[i].key.len; n++) { |
499 | 710 ch = header[i].key.data[n]; |
711 | |
509 | 712 if (ch >= 'A' && ch <= 'Z') { |
713 ch |= 0x20; | |
499 | 714 |
715 } else if (ch == '-') { | |
716 ch = '_'; | |
717 } | |
718 | |
577 | 719 if (var->data[n + prefix] != ch) { |
499 | 720 break; |
721 } | |
722 } | |
723 | |
742
75d767d32624
nonexistent $sent_http_content has value of $sent_http_content_length or so
Igor Sysoev <igor@sysoev.ru>
parents:
732
diff
changeset
|
724 if (n + prefix == var->len && n == header[i].key.len) { |
573 | 725 v->len = header[i].value.len; |
726 v->valid = 1; | |
1565 | 727 v->no_cacheable = 0; |
573 | 728 v->not_found = 0; |
729 v->data = header[i].value.data; | |
499 | 730 |
573 | 731 return NGX_OK; |
499 | 732 } |
733 } | |
734 | |
573 | 735 v->not_found = 1; |
736 | |
737 return NGX_OK; | |
509 | 738 } |
739 | |
740 | |
573 | 741 static ngx_int_t |
2307 | 742 ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v, |
743 uintptr_t data) | |
744 { | |
745 ngx_str_t *name = (ngx_str_t *) data; | |
746 | |
747 ngx_str_t cookie, s; | |
748 | |
749 s.len = name->len - (sizeof("cookie_") - 1); | |
750 s.data = name->data + sizeof("cookie_") - 1; | |
751 | |
752 if (ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &s, &cookie) | |
753 == NGX_DECLINED) | |
754 { | |
755 v->not_found = 1; | |
756 return NGX_OK; | |
757 } | |
758 | |
759 v->len = cookie.len; | |
760 v->valid = 1; | |
761 v->no_cacheable = 0; | |
762 v->not_found = 0; | |
763 v->data = cookie.data; | |
764 | |
765 return NGX_OK; | |
766 } | |
767 | |
768 | |
769 static ngx_int_t | |
2137 | 770 ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, |
771 uintptr_t data) | |
772 { | |
773 ngx_str_t *name = (ngx_str_t *) data; | |
774 | |
775 u_char *p, *arg; | |
776 size_t len; | |
777 | |
778 if (r->args.len == 0) { | |
779 v->not_found = 1; | |
780 return NGX_OK; | |
781 } | |
782 | |
783 len = name->len - 1 - (sizeof("arg_") - 1); | |
784 arg = name->data + sizeof("arg_") - 1; | |
785 | |
786 for (p = r->args.data; *p && *p != ' '; p++) { | |
787 | |
788 /* | |
789 * although r->args.data is not null-terminated by itself, | |
790 * however, there is null in the end of request line | |
791 */ | |
792 | |
793 p = ngx_strcasestrn(p, (char *) arg, len); | |
794 | |
795 if (p == NULL) { | |
796 v->not_found = 1; | |
797 return NGX_OK; | |
798 } | |
799 | |
800 if ((p == r->args.data || *(p - 1) == '&') && *(p + len + 1) == '=') { | |
801 | |
802 v->data = p + len + 2; | |
803 | |
804 p = (u_char *) ngx_strchr(p, '&'); | |
805 | |
806 if (p == NULL) { | |
807 p = r->args.data + r->args.len; | |
808 } | |
809 | |
810 v->len = p - v->data; | |
811 v->valid = 1; | |
812 v->no_cacheable = 0; | |
813 v->not_found = 0; | |
814 | |
815 return NGX_OK; | |
816 } | |
817 } | |
818 | |
819 v->not_found = 1; | |
820 | |
821 return NGX_OK; | |
822 } | |
823 | |
824 | |
825 static ngx_int_t | |
573 | 826 ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v, |
827 uintptr_t data) | |
509 | 828 { |
1811 | 829 ngx_http_core_srv_conf_t *cscf; |
830 | |
2007
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1811
diff
changeset
|
831 if (r->headers_in.server.len) { |
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1811
diff
changeset
|
832 v->len = r->headers_in.server.len; |
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1811
diff
changeset
|
833 v->data = r->headers_in.server.data; |
928
a6fe6bedb9e3
fix segfault when $host is used and
Igor Sysoev <igor@sysoev.ru>
parents:
864
diff
changeset
|
834 |
a6fe6bedb9e3
fix segfault when $host is used and
Igor Sysoev <igor@sysoev.ru>
parents:
864
diff
changeset
|
835 } else { |
2007
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1811
diff
changeset
|
836 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); |
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1811
diff
changeset
|
837 |
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1811
diff
changeset
|
838 v->len = cscf->server_name.len; |
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1811
diff
changeset
|
839 v->data = cscf->server_name.data; |
509 | 840 } |
841 | |
573 | 842 v->valid = 1; |
1565 | 843 v->no_cacheable = 0; |
573 | 844 v->not_found = 0; |
509 | 845 |
573 | 846 return NGX_OK; |
499 | 847 } |
848 | |
849 | |
573 | 850 static ngx_int_t |
983
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
851 ngx_http_variable_binary_remote_addr(ngx_http_request_t *r, |
573 | 852 ngx_http_variable_value_t *v, uintptr_t data) |
499 | 853 { |
982 | 854 struct sockaddr_in *sin; |
855 | |
983
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
856 /* AF_INET only */ |
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
857 |
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
858 sin = (struct sockaddr_in *) r->connection->sockaddr; |
982 | 859 |
983
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
860 v->len = sizeof(in_addr_t); |
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
861 v->valid = 1; |
1565 | 862 v->no_cacheable = 0; |
983
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
863 v->not_found = 0; |
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
864 v->data = (u_char *) &sin->sin_addr.s_addr; |
982 | 865 |
983
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
866 return NGX_OK; |
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
867 } |
982 | 868 |
869 | |
983
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
870 static ngx_int_t |
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
871 ngx_http_variable_remote_addr(ngx_http_request_t *r, |
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
872 ngx_http_variable_value_t *v, uintptr_t data) |
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
873 { |
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
874 v->len = r->connection->addr_text.len; |
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
875 v->valid = 1; |
1565 | 876 v->no_cacheable = 0; |
983
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
877 v->not_found = 0; |
7a8ca436d611
ngx_http_variable_binary_remote_addr()
Igor Sysoev <igor@sysoev.ru>
parents:
982
diff
changeset
|
878 v->data = r->connection->addr_text.data; |
499 | 879 |
573 | 880 return NGX_OK; |
499 | 881 } |
882 | |
883 | |
573 | 884 static ngx_int_t |
885 ngx_http_variable_remote_port(ngx_http_request_t *r, | |
886 ngx_http_variable_value_t *v, uintptr_t data) | |
499 | 887 { |
573 | 888 ngx_uint_t port; |
889 struct sockaddr_in *sin; | |
509 | 890 |
573 | 891 v->len = 0; |
892 v->valid = 1; | |
1565 | 893 v->no_cacheable = 0; |
573 | 894 v->not_found = 0; |
509 | 895 |
2049 | 896 v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1); |
573 | 897 if (v->data == NULL) { |
898 return NGX_ERROR; | |
509 | 899 } |
900 | |
901 /* AF_INET only */ | |
577 | 902 |
509 | 903 if (r->connection->sockaddr->sa_family == AF_INET) { |
904 sin = (struct sockaddr_in *) r->connection->sockaddr; | |
577 | 905 |
509 | 906 port = ntohs(sin->sin_port); |
577 | 907 |
509 | 908 if (port > 0 && port < 65536) { |
573 | 909 v->len = ngx_sprintf(v->data, "%ui", port) - v->data; |
509 | 910 } |
911 } | |
912 | |
573 | 913 return NGX_OK; |
509 | 914 } |
915 | |
916 | |
573 | 917 static ngx_int_t |
918 ngx_http_variable_server_addr(ngx_http_request_t *r, | |
919 ngx_http_variable_value_t *v, uintptr_t data) | |
509 | 920 { |
1805 | 921 ngx_str_t s; |
499 | 922 |
2197
74477ea8074f
*) remove zero termination in ngx_inet_ntop() and ngx_sock_ntop()
Igor Sysoev <igor@sysoev.ru>
parents:
2137
diff
changeset
|
923 s.data = ngx_pnalloc(r->pool, NGX_INET_ADDRSTRLEN); |
1805 | 924 if (s.data == NULL) { |
573 | 925 return NGX_ERROR; |
509 | 926 } |
927 | |
1805 | 928 if (ngx_http_server_addr(r, &s) != NGX_OK) { |
929 return NGX_ERROR; | |
509 | 930 } |
931 | |
1805 | 932 v->len = s.len; |
573 | 933 v->valid = 1; |
1565 | 934 v->no_cacheable = 0; |
573 | 935 v->not_found = 0; |
1805 | 936 v->data = s.data; |
499 | 937 |
573 | 938 return NGX_OK; |
499 | 939 } |
940 | |
941 | |
573 | 942 static ngx_int_t |
943 ngx_http_variable_server_port(ngx_http_request_t *r, | |
944 ngx_http_variable_value_t *v, uintptr_t data) | |
509 | 945 { |
573 | 946 v->len = r->port_text->len - 1; |
947 v->valid = 1; | |
1565 | 948 v->no_cacheable = 0; |
573 | 949 v->not_found = 0; |
950 v->data = r->port_text->data + 1; | |
509 | 951 |
573 | 952 return NGX_OK; |
509 | 953 } |
954 | |
955 | |
573 | 956 static ngx_int_t |
731 | 957 ngx_http_variable_scheme(ngx_http_request_t *r, |
958 ngx_http_variable_value_t *v, uintptr_t data) | |
959 { | |
960 #if (NGX_HTTP_SSL) | |
961 | |
962 if (r->connection->ssl) { | |
963 v->len = sizeof("https") - 1; | |
964 v->valid = 1; | |
1565 | 965 v->no_cacheable = 0; |
731 | 966 v->not_found = 0; |
732 | 967 v->data = (u_char *) "https"; |
731 | 968 |
969 return NGX_OK; | |
970 } | |
971 | |
972 #endif | |
973 | |
974 v->len = sizeof("http") - 1; | |
975 v->valid = 1; | |
1565 | 976 v->no_cacheable = 0; |
731 | 977 v->not_found = 0; |
732 | 978 v->data = (u_char *) "http"; |
731 | 979 |
980 return NGX_OK; | |
981 } | |
982 | |
983 | |
984 static ngx_int_t | |
1351 | 985 ngx_http_variable_is_args(ngx_http_request_t *r, |
986 ngx_http_variable_value_t *v, uintptr_t data) | |
987 { | |
988 v->valid = 1; | |
1565 | 989 v->no_cacheable = 0; |
1351 | 990 v->not_found = 0; |
991 | |
992 if (r->args.len == 0) { | |
993 v->len = 0; | |
994 v->data = NULL; | |
995 return NGX_OK; | |
996 } | |
997 | |
998 v->len = 1; | |
999 v->data = (u_char *) "?"; | |
1000 | |
1001 return NGX_OK; | |
1002 } | |
1003 | |
1004 | |
1005 static ngx_int_t | |
573 | 1006 ngx_http_variable_document_root(ngx_http_request_t *r, |
1007 ngx_http_variable_value_t *v, uintptr_t data) | |
499 | 1008 { |
671 | 1009 ngx_str_t path; |
573 | 1010 ngx_http_core_loc_conf_t *clcf; |
509 | 1011 |
1012 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
1013 | |
671 | 1014 if (clcf->root_lengths == NULL) { |
1015 v->len = clcf->root.len; | |
1016 v->valid = 1; | |
1565 | 1017 v->no_cacheable = 0; |
671 | 1018 v->not_found = 0; |
1019 v->data = clcf->root.data; | |
1020 | |
1021 } else { | |
1022 if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 0, | |
1023 clcf->root_values->elts) | |
1024 == NULL) | |
1025 { | |
1026 return NGX_ERROR; | |
1027 } | |
1028 | |
1352 | 1029 if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) |
1030 == NGX_ERROR) | |
1031 { | |
671 | 1032 return NGX_ERROR; |
1033 } | |
1034 | |
1035 v->len = path.len; | |
1036 v->valid = 1; | |
1565 | 1037 v->no_cacheable = 0; |
671 | 1038 v->not_found = 0; |
1039 v->data = path.data; | |
1040 } | |
509 | 1041 |
573 | 1042 return NGX_OK; |
509 | 1043 } |
1044 | |
1045 | |
573 | 1046 static ngx_int_t |
2259 | 1047 ngx_http_variable_realpath_root(ngx_http_request_t *r, |
1048 ngx_http_variable_value_t *v, uintptr_t data) | |
1049 { | |
1050 size_t len; | |
1051 ngx_str_t path; | |
1052 ngx_http_core_loc_conf_t *clcf; | |
1053 u_char real[NGX_MAX_PATH]; | |
1054 | |
1055 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
1056 | |
1057 if (clcf->root_lengths == NULL) { | |
1058 path = clcf->root; | |
1059 | |
1060 } else { | |
1061 if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 1, | |
1062 clcf->root_values->elts) | |
1063 == NULL) | |
1064 { | |
1065 return NGX_ERROR; | |
1066 } | |
1067 | |
1068 path.data[path.len - 1] = '\0'; | |
1069 | |
1070 if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) | |
1071 == NGX_ERROR) | |
1072 { | |
1073 return NGX_ERROR; | |
1074 } | |
1075 } | |
1076 | |
1077 if (ngx_realpath(path.data, real) == NULL) { | |
1078 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, | |
1079 ngx_realpath_n " \"%s\" failed", path.data); | |
1080 return NGX_ERROR; | |
1081 } | |
1082 | |
1083 len = ngx_strlen(real); | |
1084 | |
1085 v->data = ngx_pnalloc(r->pool, len); | |
1086 if (v->data == NULL) { | |
1087 return NGX_ERROR; | |
1088 } | |
1089 | |
1090 v->len = len; | |
1091 v->valid = 1; | |
1092 v->no_cacheable = 0; | |
1093 v->not_found = 0; | |
1094 | |
1095 ngx_memcpy(v->data, real, len); | |
1096 | |
1097 return NGX_OK; | |
1098 } | |
1099 | |
1100 | |
1101 static ngx_int_t | |
573 | 1102 ngx_http_variable_request_filename(ngx_http_request_t *r, |
1103 ngx_http_variable_value_t *v, uintptr_t data) | |
509 | 1104 { |
773 | 1105 size_t root; |
573 | 1106 ngx_str_t path; |
499 | 1107 |
773 | 1108 if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) { |
573 | 1109 return NGX_ERROR; |
557 | 1110 } |
509 | 1111 |
557 | 1112 /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */ |
509 | 1113 |
573 | 1114 v->len = path.len - 1; |
1115 v->valid = 1; | |
1565 | 1116 v->no_cacheable = 0; |
573 | 1117 v->not_found = 0; |
1118 v->data = path.data; | |
499 | 1119 |
573 | 1120 return NGX_OK; |
499 | 1121 } |
1122 | |
1123 | |
573 | 1124 static ngx_int_t |
1811 | 1125 ngx_http_variable_server_name(ngx_http_request_t *r, |
1126 ngx_http_variable_value_t *v, uintptr_t data) | |
1127 { | |
1128 ngx_http_core_srv_conf_t *cscf; | |
1129 | |
1130 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); | |
1131 | |
1132 v->len = cscf->server_name.len; | |
1133 v->valid = 1; | |
1134 v->no_cacheable = 0; | |
1135 v->not_found = 0; | |
1136 v->data = cscf->server_name.data; | |
1137 | |
1138 return NGX_OK; | |
1139 } | |
1140 | |
1141 | |
1142 static ngx_int_t | |
573 | 1143 ngx_http_variable_request_method(ngx_http_request_t *r, |
1144 ngx_http_variable_value_t *v, uintptr_t data) | |
561 | 1145 { |
647 | 1146 if (r->main->method_name.data) { |
1147 v->len = r->main->method_name.len; | |
573 | 1148 v->valid = 1; |
1565 | 1149 v->no_cacheable = 0; |
573 | 1150 v->not_found = 0; |
647 | 1151 v->data = r->main->method_name.data; |
573 | 1152 |
1153 } else { | |
1154 v->not_found = 1; | |
561 | 1155 } |
1156 | |
573 | 1157 return NGX_OK; |
561 | 1158 } |
1159 | |
1160 | |
573 | 1161 static ngx_int_t |
1162 ngx_http_variable_remote_user(ngx_http_request_t *r, | |
1163 ngx_http_variable_value_t *v, uintptr_t data) | |
539 | 1164 { |
573 | 1165 ngx_int_t rc; |
539 | 1166 |
1167 rc = ngx_http_auth_basic_user(r); | |
1168 | |
1169 if (rc == NGX_DECLINED) { | |
573 | 1170 v->not_found = 1; |
1171 return NGX_OK; | |
539 | 1172 } |
1173 | |
1174 if (rc == NGX_ERROR) { | |
573 | 1175 return NGX_ERROR; |
539 | 1176 } |
1177 | |
573 | 1178 v->len = r->headers_in.user.len; |
1179 v->valid = 1; | |
1565 | 1180 v->no_cacheable = 0; |
573 | 1181 v->not_found = 0; |
1182 v->data = r->headers_in.user.data; | |
571 | 1183 |
573 | 1184 return NGX_OK; |
571 | 1185 } |
1186 | |
1187 | |
611 | 1188 static ngx_int_t |
1189 ngx_http_variable_body_bytes_sent(ngx_http_request_t *r, | |
1190 ngx_http_variable_value_t *v, uintptr_t data) | |
1191 { | |
1192 off_t sent; | |
1193 u_char *p; | |
1194 | |
1195 sent = r->connection->sent - r->header_size; | |
1196 | |
1197 if (sent < 0) { | |
1198 sent = 0; | |
1199 } | |
1200 | |
2049 | 1201 p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN); |
611 | 1202 if (p == NULL) { |
1203 return NGX_ERROR; | |
1204 } | |
1205 | |
1206 v->len = ngx_sprintf(p, "%O", sent) - p; | |
1207 v->valid = 1; | |
1565 | 1208 v->no_cacheable = 0; |
611 | 1209 v->not_found = 0; |
1210 v->data = p; | |
1211 | |
1212 return NGX_OK; | |
1213 } | |
1214 | |
1215 | |
629 | 1216 static ngx_int_t |
641 | 1217 ngx_http_variable_sent_content_type(ngx_http_request_t *r, |
1218 ngx_http_variable_value_t *v, uintptr_t data) | |
1219 { | |
1220 if (r->headers_out.content_type.len) { | |
1221 v->len = r->headers_out.content_type.len; | |
1222 v->valid = 1; | |
1565 | 1223 v->no_cacheable = 0; |
641 | 1224 v->not_found = 0; |
1225 v->data = r->headers_out.content_type.data; | |
1226 | |
1227 } else { | |
1228 v->not_found = 1; | |
1229 } | |
1230 | |
1231 return NGX_OK; | |
1232 } | |
1233 | |
1234 | |
1235 static ngx_int_t | |
1236 ngx_http_variable_sent_content_length(ngx_http_request_t *r, | |
1237 ngx_http_variable_value_t *v, uintptr_t data) | |
1238 { | |
1239 u_char *p; | |
1240 | |
1241 if (r->headers_out.content_length) { | |
1242 v->len = r->headers_out.content_length->value.len; | |
1243 v->valid = 1; | |
1565 | 1244 v->no_cacheable = 0; |
641 | 1245 v->not_found = 0; |
1246 v->data = r->headers_out.content_length->value.data; | |
1247 | |
1248 return NGX_OK; | |
1249 } | |
1250 | |
1251 if (r->headers_out.content_length_n >= 0) { | |
2049 | 1252 p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN); |
641 | 1253 if (p == NULL) { |
1254 return NGX_ERROR; | |
1255 } | |
1256 | |
1257 v->len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) - p; | |
1258 v->valid = 1; | |
1565 | 1259 v->no_cacheable = 0; |
641 | 1260 v->not_found = 0; |
1261 v->data = p; | |
1262 | |
1263 return NGX_OK; | |
1264 } | |
1265 | |
1266 v->not_found = 1; | |
1267 | |
1268 return NGX_OK; | |
1269 } | |
1270 | |
1271 | |
1272 static ngx_int_t | |
1273 ngx_http_variable_sent_last_modified(ngx_http_request_t *r, | |
1274 ngx_http_variable_value_t *v, uintptr_t data) | |
1275 { | |
1276 u_char *p; | |
1277 | |
1278 if (r->headers_out.last_modified) { | |
1279 v->len = r->headers_out.last_modified->value.len; | |
1280 v->valid = 1; | |
1565 | 1281 v->no_cacheable = 0; |
641 | 1282 v->not_found = 0; |
1283 v->data = r->headers_out.last_modified->value.data; | |
1284 | |
1285 return NGX_OK; | |
1286 } | |
1287 | |
1288 if (r->headers_out.last_modified_time >= 0) { | |
2049 | 1289 p = ngx_pnalloc(r->pool, |
641 | 1290 sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT") - 1); |
1291 if (p == NULL) { | |
1292 return NGX_ERROR; | |
1293 } | |
1294 | |
1295 v->len = ngx_http_time(p, r->headers_out.last_modified_time) - p; | |
1296 v->valid = 1; | |
1565 | 1297 v->no_cacheable = 0; |
641 | 1298 v->not_found = 0; |
1299 v->data = p; | |
1300 | |
1301 return NGX_OK; | |
1302 } | |
1303 | |
1304 v->not_found = 1; | |
1305 | |
1306 return NGX_OK; | |
1307 } | |
1308 | |
1309 | |
1310 static ngx_int_t | |
1311 ngx_http_variable_sent_connection(ngx_http_request_t *r, | |
1312 ngx_http_variable_value_t *v, uintptr_t data) | |
1313 { | |
1314 size_t len; | |
1315 char *p; | |
1316 | |
1317 if (r->keepalive) { | |
1318 len = sizeof("keep-alive") - 1; | |
1319 p = "keep-alive"; | |
1320 | |
1321 } else { | |
1322 len = sizeof("close") - 1; | |
1323 p = "close"; | |
1324 } | |
1325 | |
1326 v->len = len; | |
1327 v->valid = 1; | |
1565 | 1328 v->no_cacheable = 0; |
641 | 1329 v->not_found = 0; |
1330 v->data = (u_char *) p; | |
1331 | |
1332 return NGX_OK; | |
1333 } | |
1334 | |
1335 | |
1336 static ngx_int_t | |
1337 ngx_http_variable_sent_keep_alive(ngx_http_request_t *r, | |
1338 ngx_http_variable_value_t *v, uintptr_t data) | |
1339 { | |
1340 u_char *p; | |
1341 ngx_http_core_loc_conf_t *clcf; | |
1342 | |
1343 if (r->keepalive) { | |
1344 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
1345 | |
1346 if (clcf->keepalive_header) { | |
1347 | |
2049 | 1348 p = ngx_pnalloc(r->pool, sizeof("timeout=") - 1 + NGX_TIME_T_LEN); |
641 | 1349 if (p == NULL) { |
1350 return NGX_ERROR; | |
1351 } | |
1352 | |
1353 v->len = ngx_sprintf(p, "timeout=%T", clcf->keepalive_header) - p; | |
1354 v->valid = 1; | |
1565 | 1355 v->no_cacheable = 0; |
641 | 1356 v->not_found = 0; |
1357 v->data = p; | |
1358 | |
1359 return NGX_OK; | |
1360 } | |
1361 } | |
1362 | |
1363 v->not_found = 1; | |
1364 | |
1365 return NGX_OK; | |
1366 } | |
1367 | |
1368 | |
1369 static ngx_int_t | |
1370 ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r, | |
1371 ngx_http_variable_value_t *v, uintptr_t data) | |
1372 { | |
1373 if (r->chunked) { | |
1374 v->len = sizeof("chunked") - 1; | |
1375 v->valid = 1; | |
1565 | 1376 v->no_cacheable = 0; |
641 | 1377 v->not_found = 0; |
1378 v->data = (u_char *) "chunked"; | |
1379 | |
1380 } else { | |
1381 v->not_found = 1; | |
1382 } | |
1383 | |
1384 return NGX_OK; | |
1385 } | |
1386 | |
1387 | |
1388 static ngx_int_t | |
629 | 1389 ngx_http_variable_request_completion(ngx_http_request_t *r, |
1390 ngx_http_variable_value_t *v, uintptr_t data) | |
1391 { | |
1392 if (r->request_complete) { | |
1393 v->len = 2; | |
1394 v->valid = 1; | |
1565 | 1395 v->no_cacheable = 0; |
629 | 1396 v->not_found = 0; |
1397 v->data = (u_char *) "OK"; | |
1398 | |
1399 return NGX_OK; | |
1400 } | |
1401 | |
1402 v->len = 0; | |
1403 v->valid = 1; | |
1565 | 1404 v->no_cacheable = 0; |
629 | 1405 v->not_found = 0; |
1406 v->data = (u_char *) ""; | |
1407 | |
1408 return NGX_OK; | |
1409 } | |
1410 | |
1411 | |
759 | 1412 static ngx_int_t |
1413 ngx_http_variable_request_body_file(ngx_http_request_t *r, | |
1414 ngx_http_variable_value_t *v, uintptr_t data) | |
1415 { | |
1416 if (r->request_body == NULL || r->request_body->temp_file == NULL) { | |
763
0b0f3d4854c0
variable should not be found if no request body file
Igor Sysoev <igor@sysoev.ru>
parents:
759
diff
changeset
|
1417 v->not_found = 1; |
759 | 1418 |
1419 return NGX_OK; | |
1420 } | |
1421 | |
1422 v->len = r->request_body->temp_file->file.name.len; | |
1423 v->valid = 1; | |
1565 | 1424 v->no_cacheable = 0; |
759 | 1425 v->not_found = 0; |
1426 v->data = r->request_body->temp_file->file.name.data; | |
1427 | |
1428 return NGX_OK; | |
1429 } | |
1430 | |
1431 | |
1329 | 1432 static ngx_int_t |
1433 ngx_http_variable_nginx_version(ngx_http_request_t *r, | |
1434 ngx_http_variable_value_t *v, uintptr_t data) | |
1435 { | |
1436 v->len = sizeof(NGINX_VERSION) - 1; | |
1437 v->valid = 1; | |
1565 | 1438 v->no_cacheable = 0; |
1329 | 1439 v->not_found = 0; |
1440 v->data = (u_char *) NGINX_VERSION; | |
1441 | |
1442 return NGX_OK; | |
1443 } | |
1444 | |
1445 | |
2011 | 1446 static ngx_int_t |
1447 ngx_http_variable_hostname(ngx_http_request_t *r, | |
1448 ngx_http_variable_value_t *v, uintptr_t data) | |
1449 { | |
1450 v->len = ngx_cycle->hostname.len; | |
1451 v->valid = 1; | |
1452 v->no_cacheable = 0; | |
1453 v->not_found = 0; | |
1454 v->data = ngx_cycle->hostname.data; | |
1455 | |
1456 return NGX_OK; | |
1457 } | |
1458 | |
1459 | |
2249 | 1460 static ngx_int_t |
1461 ngx_http_variable_pid(ngx_http_request_t *r, | |
1462 ngx_http_variable_value_t *v, uintptr_t data) | |
1463 { | |
1464 u_char *p; | |
1465 | |
1466 p = ngx_pnalloc(r->pool, NGX_INT64_LEN); | |
1467 if (p == NULL) { | |
1468 return NGX_ERROR; | |
1469 } | |
1470 | |
1471 v->len = ngx_sprintf(p, "%P", ngx_pid) - p; | |
1472 v->valid = 1; | |
1473 v->no_cacheable = 0; | |
1474 v->not_found = 0; | |
1475 v->data = p; | |
1476 | |
1477 return NGX_OK; | |
1478 } | |
1479 | |
1480 | |
499 | 1481 ngx_int_t |
509 | 1482 ngx_http_variables_add_core_vars(ngx_conf_t *cf) |
499 | 1483 { |
611 | 1484 ngx_int_t rc; |
1485 ngx_http_variable_t *v; | |
501 | 1486 ngx_http_core_main_conf_t *cmcf; |
499 | 1487 |
509 | 1488 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); |
1489 | |
611 | 1490 cmcf->variables_keys = ngx_pcalloc(cf->temp_pool, |
1491 sizeof(ngx_hash_keys_arrays_t)); | |
1492 if (cmcf->variables_keys == NULL) { | |
1493 return NGX_ERROR; | |
1494 } | |
1495 | |
1496 cmcf->variables_keys->pool = cf->pool; | |
1497 cmcf->variables_keys->temp_pool = cf->pool; | |
1498 | |
1499 if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL) | |
1500 != NGX_OK) | |
509 | 1501 { |
499 | 1502 return NGX_ERROR; |
1503 } | |
1504 | |
611 | 1505 for (v = ngx_http_core_variables; v->name.len; v++) { |
1506 rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, | |
1507 NGX_HASH_READONLY_KEY); | |
1508 | |
1509 if (rc == NGX_OK) { | |
1510 continue; | |
499 | 1511 } |
1512 | |
611 | 1513 if (rc == NGX_BUSY) { |
1514 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1515 "conflicting variable name \"%V\"", &v->name); | |
1516 } | |
1517 | |
1518 return NGX_ERROR; | |
499 | 1519 } |
1520 | |
1521 return NGX_OK; | |
1522 } | |
509 | 1523 |
1524 | |
1525 ngx_int_t | |
1526 ngx_http_variables_init_vars(ngx_conf_t *cf) | |
1527 { | |
1528 ngx_uint_t i, n; | |
611 | 1529 ngx_hash_key_t *key; |
1530 ngx_hash_init_t hash; | |
509 | 1531 ngx_http_variable_t *v, *av; |
1532 ngx_http_core_main_conf_t *cmcf; | |
1533 | |
1534 /* set the handlers for the indexed http variables */ | |
1535 | |
1536 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); | |
1537 | |
1538 v = cmcf->variables.elts; | |
611 | 1539 key = cmcf->variables_keys->keys.elts; |
509 | 1540 |
1541 for (i = 0; i < cmcf->variables.nelts; i++) { | |
1542 | |
611 | 1543 for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) { |
509 | 1544 |
1191
0eb2dc4fdea8
fix segfault introduced in r1190
Igor Sysoev <igor@sysoev.ru>
parents:
1173
diff
changeset
|
1545 av = key[n].value; |
0eb2dc4fdea8
fix segfault introduced in r1190
Igor Sysoev <igor@sysoev.ru>
parents:
1173
diff
changeset
|
1546 |
0eb2dc4fdea8
fix segfault introduced in r1190
Igor Sysoev <igor@sysoev.ru>
parents:
1173
diff
changeset
|
1547 if (av->get_handler |
0eb2dc4fdea8
fix segfault introduced in r1190
Igor Sysoev <igor@sysoev.ru>
parents:
1173
diff
changeset
|
1548 && v[i].name.len == key[n].key.len |
611 | 1549 && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len) |
509 | 1550 == 0) |
1551 { | |
637 | 1552 v[i].get_handler = av->get_handler; |
611 | 1553 v[i].data = av->data; |
527 | 1554 |
611 | 1555 av->flags |= NGX_HTTP_VAR_INDEXED; |
1556 v[i].flags = av->flags; | |
509 | 1557 |
611 | 1558 av->index = i; |
533 | 1559 |
509 | 1560 goto next; |
1561 } | |
1562 } | |
1563 | |
1564 if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) { | |
637 | 1565 v[i].get_handler = ngx_http_variable_unknown_header_in; |
577 | 1566 v[i].data = (uintptr_t) &v[i].name; |
1567 | |
1568 continue; | |
1569 } | |
1570 | |
1571 if (ngx_strncmp(v[i].name.data, "sent_http_", 10) == 0) { | |
637 | 1572 v[i].get_handler = ngx_http_variable_unknown_header_out; |
509 | 1573 v[i].data = (uintptr_t) &v[i].name; |
1574 | |
1575 continue; | |
1576 } | |
1577 | |
1162 | 1578 if (ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0) { |
1579 v[i].get_handler = ngx_http_upstream_header_variable; | |
1580 v[i].data = (uintptr_t) &v[i].name; | |
1565 | 1581 v[i].flags = NGX_HTTP_VAR_NOCACHEABLE; |
1162 | 1582 |
1583 continue; | |
1584 } | |
1585 | |
2307 | 1586 if (ngx_strncmp(v[i].name.data, "cookie_", 7) == 0) { |
1587 v[i].get_handler = ngx_http_variable_cookie; | |
1588 v[i].data = (uintptr_t) &v[i].name; | |
1589 | |
1590 continue; | |
1591 } | |
1592 | |
2137 | 1593 if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) { |
1594 v[i].get_handler = ngx_http_variable_argument; | |
1595 v[i].data = (uintptr_t) &v[i].name; | |
1596 | |
1597 continue; | |
1598 } | |
1599 | |
509 | 1600 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, |
1601 "unknown \"%V\" variable", &v[i].name); | |
1602 | |
1603 return NGX_ERROR; | |
1604 | |
1605 next: | |
1606 continue; | |
1607 } | |
1608 | |
1609 | |
611 | 1610 for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) { |
1611 av = key[n].value; | |
1612 | |
1613 if (av->flags & NGX_HTTP_VAR_NOHASH) { | |
1614 key[n].key.data = NULL; | |
583 | 1615 } |
1616 } | |
1617 | |
1618 | |
611 | 1619 hash.hash = &cmcf->variables_hash; |
1620 hash.key = ngx_hash_key; | |
1621 hash.max_size = cmcf->variables_hash_max_size; | |
1622 hash.bucket_size = cmcf->variables_hash_bucket_size; | |
1623 hash.name = "variables_hash"; | |
1624 hash.pool = cf->pool; | |
1625 hash.temp_pool = NULL; | |
509 | 1626 |
611 | 1627 if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts, |
1628 cmcf->variables_keys->keys.nelts) | |
581 | 1629 != NGX_OK) |
509 | 1630 { |
1631 return NGX_ERROR; | |
1632 } | |
1633 | |
611 | 1634 cmcf->variables_keys = NULL; |
509 | 1635 |
1636 return NGX_OK; | |
1637 } | |
2333
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1638 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1639 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1640 void |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1641 ngx_http_variable_value_rbtree_insert(ngx_rbtree_node_t *temp, |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1642 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1643 { |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1644 ngx_rbtree_node_t **p; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1645 ngx_http_variable_value_node_t *vvn, *vvt; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1646 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1647 for ( ;; ) { |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1648 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1649 vvn = (ngx_http_variable_value_node_t *) node; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1650 vvt = (ngx_http_variable_value_node_t *) temp; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1651 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1652 if (node->key != temp->key) { |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1653 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1654 p = (node->key < temp->key) ? &temp->left : &temp->right; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1655 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1656 } else if (vvn->len != vvt->len) { |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1657 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1658 p = (vvn->len < vvt->len) ? &temp->left : &temp->right; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1659 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1660 } else { |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1661 p = (ngx_memcmp(vvn->value->data, vvt->value->data, vvn->len) < 0) |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1662 ? &temp->left : &temp->right; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1663 } |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1664 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1665 if (*p == sentinel) { |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1666 break; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1667 } |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1668 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1669 temp = *p; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1670 } |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1671 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1672 *p = node; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1673 node->parent = temp; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1674 node->left = sentinel; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1675 node->right = sentinel; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1676 ngx_rbt_red(node); |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1677 } |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1678 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1679 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1680 ngx_http_variable_value_t * |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1681 ngx_http_variable_value_lookup(ngx_rbtree_t *rbtree, ngx_str_t *val, |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1682 uint32_t hash) |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1683 { |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1684 ngx_int_t rc; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1685 ngx_rbtree_node_t *node, *sentinel; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1686 ngx_http_variable_value_node_t *vvn; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1687 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1688 node = rbtree->root; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1689 sentinel = rbtree->sentinel; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1690 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1691 while (node != sentinel) { |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1692 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1693 vvn = (ngx_http_variable_value_node_t *) node; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1694 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1695 if (hash != node->key) { |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1696 node = (hash < node->key) ? node->left : node->right; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1697 continue; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1698 } |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1699 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1700 if (val->len != vvn->len) { |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1701 node = (val->len < vvn->len) ? node->left : node->right; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1702 continue; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1703 } |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1704 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1705 rc = ngx_memcmp(val->data, vvn->value->data, val->len); |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1706 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1707 if (rc < 0) { |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1708 node = node->left; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1709 continue; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1710 } |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1711 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1712 if (rc > 0) { |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1713 node = node->right; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1714 continue; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1715 } |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1716 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1717 return vvn->value; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1718 } |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1719 |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1720 return NULL; |
f267d23868fc
variable value rbtree support
Igor Sysoev <igor@sysoev.ru>
parents:
2307
diff
changeset
|
1721 } |