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