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