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