3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
14 static ngx_int_t
ngx_http_variable_request(ngx_http_request_t
*r
,
15 ngx_http_variable_value_t
*v
, uintptr_t data
);
16 static void ngx_http_variable_request_set(ngx_http_request_t
*r
,
17 ngx_http_variable_value_t
*v
, uintptr_t data
);
18 static void ngx_http_variable_request_set_size(ngx_http_request_t
*r
,
19 ngx_http_variable_value_t
*v
, uintptr_t data
);
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
);
25 static ngx_int_t
ngx_http_variable_unknown_header_in(ngx_http_request_t
*r
,
26 ngx_http_variable_value_t
*v
, uintptr_t data
);
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
);
29 static ngx_int_t
ngx_http_variable_argument(ngx_http_request_t
*r
,
30 ngx_http_variable_value_t
*v
, uintptr_t data
);
32 static ngx_int_t
ngx_http_variable_host(ngx_http_request_t
*r
,
33 ngx_http_variable_value_t
*v
, uintptr_t data
);
34 static ngx_int_t
ngx_http_variable_binary_remote_addr(ngx_http_request_t
*r
,
35 ngx_http_variable_value_t
*v
, uintptr_t data
);
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
);
44 static ngx_int_t
ngx_http_variable_scheme(ngx_http_request_t
*r
,
45 ngx_http_variable_value_t
*v
, uintptr_t data
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
80 static ngx_int_t
ngx_http_variable_hostname(ngx_http_request_t
*r
,
81 ngx_http_variable_value_t
*v
, uintptr_t data
);
85 * Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED
86 * REMOTE_HOST (null), REMOTE_IDENT (null),
89 * Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner)
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
99 static ngx_http_variable_t ngx_http_core_variables
[] = {
101 { ngx_string("http_host"), NULL
, ngx_http_variable_header
,
102 offsetof(ngx_http_request_t
, headers_in
.host
), 0, 0 },
104 { ngx_string("http_user_agent"), NULL
, ngx_http_variable_header
,
105 offsetof(ngx_http_request_t
, headers_in
.user_agent
), 0, 0 },
107 { ngx_string("http_referer"), NULL
, ngx_http_variable_header
,
108 offsetof(ngx_http_request_t
, headers_in
.referer
), 0, 0 },
111 { ngx_string("http_via"), NULL
, ngx_http_variable_header
,
112 offsetof(ngx_http_request_t
, headers_in
.via
), 0, 0 },
115 #if (NGX_HTTP_PROXY || NGX_HTTP_REALIP)
116 { ngx_string("http_x_forwarded_for"), NULL
, ngx_http_variable_header
,
117 offsetof(ngx_http_request_t
, headers_in
.x_forwarded_for
), 0, 0 },
120 { ngx_string("http_cookie"), NULL
, ngx_http_variable_headers
,
121 offsetof(ngx_http_request_t
, headers_in
.cookies
), 0, 0 },
123 { ngx_string("content_length"), NULL
, ngx_http_variable_header
,
124 offsetof(ngx_http_request_t
, headers_in
.content_length
), 0, 0 },
126 { ngx_string("content_type"), NULL
, ngx_http_variable_header
,
127 offsetof(ngx_http_request_t
, headers_in
.content_type
), 0, 0 },
129 { ngx_string("host"), NULL
, ngx_http_variable_host
, 0, 0, 0 },
131 { ngx_string("binary_remote_addr"), NULL
,
132 ngx_http_variable_binary_remote_addr
, 0, 0, 0 },
134 { ngx_string("remote_addr"), NULL
, ngx_http_variable_remote_addr
, 0, 0, 0 },
136 { ngx_string("remote_port"), NULL
, ngx_http_variable_remote_port
, 0, 0, 0 },
138 { ngx_string("server_addr"), NULL
, ngx_http_variable_server_addr
, 0, 0, 0 },
140 { ngx_string("server_port"), NULL
, ngx_http_variable_server_port
, 0, 0, 0 },
142 { ngx_string("server_protocol"), NULL
, ngx_http_variable_request
,
143 offsetof(ngx_http_request_t
, http_protocol
), 0, 0 },
145 { ngx_string("scheme"), NULL
, ngx_http_variable_scheme
, 0, 0, 0 },
147 { ngx_string("request_uri"), NULL
, ngx_http_variable_request
,
148 offsetof(ngx_http_request_t
, unparsed_uri
), 0, 0 },
150 { ngx_string("uri"), NULL
, ngx_http_variable_request
,
151 offsetof(ngx_http_request_t
, uri
),
152 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
154 { ngx_string("document_uri"), NULL
, ngx_http_variable_request
,
155 offsetof(ngx_http_request_t
, uri
),
156 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
158 { ngx_string("request"), NULL
, ngx_http_variable_request
,
159 offsetof(ngx_http_request_t
, request_line
), 0, 0 },
161 { ngx_string("document_root"), NULL
,
162 ngx_http_variable_document_root
, 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
164 { ngx_string("query_string"), NULL
, ngx_http_variable_request
,
165 offsetof(ngx_http_request_t
, args
),
166 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
168 { ngx_string("args"),
169 ngx_http_variable_request_set
,
170 ngx_http_variable_request
,
171 offsetof(ngx_http_request_t
, args
),
172 NGX_HTTP_VAR_CHANGEABLE
|NGX_HTTP_VAR_NOCACHEABLE
, 0 },
174 { ngx_string("is_args"), NULL
, ngx_http_variable_is_args
,
175 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
177 { ngx_string("request_filename"), NULL
,
178 ngx_http_variable_request_filename
, 0,
179 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
181 { ngx_string("server_name"), NULL
, ngx_http_variable_server_name
, 0, 0, 0 },
183 { ngx_string("request_method"), NULL
,
184 ngx_http_variable_request_method
, 0, 0, 0 },
186 { ngx_string("remote_user"), NULL
, ngx_http_variable_remote_user
, 0, 0, 0 },
188 { ngx_string("body_bytes_sent"), NULL
, ngx_http_variable_body_bytes_sent
,
191 { ngx_string("request_completion"), NULL
,
192 ngx_http_variable_request_completion
,
195 { ngx_string("request_body_file"), NULL
,
196 ngx_http_variable_request_body_file
,
199 { ngx_string("sent_http_content_type"), NULL
,
200 ngx_http_variable_sent_content_type
, 0, 0, 0 },
202 { ngx_string("sent_http_content_length"), NULL
,
203 ngx_http_variable_sent_content_length
, 0, 0, 0 },
205 { ngx_string("sent_http_last_modified"), NULL
,
206 ngx_http_variable_sent_last_modified
, 0, 0, 0 },
208 { ngx_string("sent_http_connection"), NULL
,
209 ngx_http_variable_sent_connection
, 0, 0, 0 },
211 { ngx_string("sent_http_keep_alive"), NULL
,
212 ngx_http_variable_sent_keep_alive
, 0, 0, 0 },
214 { ngx_string("sent_http_transfer_encoding"), NULL
,
215 ngx_http_variable_sent_transfer_encoding
, 0, 0, 0 },
217 { ngx_string("sent_http_cache_control"), NULL
, ngx_http_variable_headers
,
218 offsetof(ngx_http_request_t
, headers_out
.cache_control
), 0, 0 },
220 { ngx_string("limit_rate"), ngx_http_variable_request_set_size
,
221 ngx_http_variable_request
,
222 offsetof(ngx_http_request_t
, limit_rate
),
223 NGX_HTTP_VAR_CHANGEABLE
|NGX_HTTP_VAR_NOCACHEABLE
, 0 },
225 { ngx_string("nginx_version"), NULL
, ngx_http_variable_nginx_version
,
228 { ngx_string("hostname"), NULL
, ngx_http_variable_hostname
,
231 { ngx_null_string
, NULL
, NULL
, 0, 0, 0 }
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");
241 ngx_http_variable_t
*
242 ngx_http_add_variable(ngx_conf_t
*cf
, ngx_str_t
*name
, ngx_uint_t flags
)
247 ngx_http_variable_t
*v
;
248 ngx_http_core_main_conf_t
*cmcf
;
250 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
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)
262 if (!(v
->flags
& NGX_HTTP_VAR_CHANGEABLE
)) {
263 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
264 "the duplicate \"%V\" variable", name
);
271 v
= ngx_palloc(cf
->pool
, sizeof(ngx_http_variable_t
));
276 v
->name
.len
= name
->len
;
277 v
->name
.data
= ngx_pnalloc(cf
->pool
, name
->len
);
278 if (v
->name
.data
== NULL
) {
282 ngx_strlow(v
->name
.data
, name
->data
, name
->len
);
284 v
->set_handler
= NULL
;
285 v
->get_handler
= NULL
;
290 rc
= ngx_hash_add_key(cmcf
->variables_keys
, &v
->name
, v
, 0);
292 if (rc
== NGX_ERROR
) {
296 if (rc
== NGX_BUSY
) {
297 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
298 "conflicting variable name \"%V\"", name
);
307 ngx_http_get_variable_index(ngx_conf_t
*cf
, ngx_str_t
*name
)
310 ngx_http_variable_t
*v
;
311 ngx_http_core_main_conf_t
*cmcf
;
313 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
315 v
= cmcf
->variables
.elts
;
318 if (ngx_array_init(&cmcf
->variables
, cf
->pool
, 4,
319 sizeof(ngx_http_variable_t
)) == NGX_ERROR
)
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)
336 v
= ngx_array_push(&cmcf
->variables
);
341 v
->name
.len
= name
->len
;
342 v
->name
.data
= ngx_pnalloc(cf
->pool
, name
->len
);
343 if (v
->name
.data
== NULL
) {
347 ngx_strlow(v
->name
.data
, name
->data
, name
->len
);
349 v
->set_handler
= NULL
;
350 v
->get_handler
= NULL
;
353 v
->index
= cmcf
->variables
.nelts
- 1;
355 return cmcf
->variables
.nelts
- 1;
359 ngx_http_variable_value_t
*
360 ngx_http_get_indexed_variable(ngx_http_request_t
*r
, ngx_uint_t index
)
362 ngx_http_variable_t
*v
;
363 ngx_http_core_main_conf_t
*cmcf
;
365 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
367 if (cmcf
->variables
.nelts
<= index
) {
368 ngx_log_error(NGX_LOG_ALERT
, r
->connection
->log
, 0,
369 "unknown variable index: %d", index
);
373 if (r
->variables
[index
].not_found
|| r
->variables
[index
].valid
) {
374 return &r
->variables
[index
];
377 v
= cmcf
->variables
.elts
;
379 if (v
[index
].get_handler(r
, &r
->variables
[index
], v
[index
].data
)
382 if (v
[index
].flags
& NGX_HTTP_VAR_NOCACHEABLE
) {
383 r
->variables
[index
].no_cacheable
= 1;
386 return &r
->variables
[index
];
389 r
->variables
[index
].valid
= 0;
390 r
->variables
[index
].not_found
= 1;
396 ngx_http_variable_value_t
*
397 ngx_http_get_flushed_variable(ngx_http_request_t
*r
, ngx_uint_t index
)
399 ngx_http_variable_value_t
*v
;
401 v
= &r
->variables
[index
];
404 if (!v
->no_cacheable
) {
412 return ngx_http_get_indexed_variable(r
, index
);
416 ngx_http_variable_value_t
*
417 ngx_http_get_variable(ngx_http_request_t
*r
, ngx_str_t
*name
, ngx_uint_t key
,
420 ngx_http_variable_t
*v
;
421 ngx_http_variable_value_t
*vv
;
422 ngx_http_core_main_conf_t
*cmcf
;
424 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
426 v
= ngx_hash_find(&cmcf
->variables_hash
, key
, name
->data
, name
->len
);
429 if (v
->flags
& NGX_HTTP_VAR_INDEXED
) {
430 return ngx_http_get_indexed_variable(r
, v
->index
);
434 vv
= ngx_palloc(r
->pool
, sizeof(ngx_http_variable_value_t
));
436 if (vv
&& v
->get_handler(r
, vv
, v
->data
) == NGX_OK
) {
444 vv
= ngx_palloc(r
->pool
, sizeof(ngx_http_variable_value_t
));
449 if (ngx_strncmp(name
->data
, "http_", 5) == 0) {
451 if (ngx_http_variable_unknown_header_in(r
, vv
, (uintptr_t) name
)
460 if (ngx_strncmp(name
->data
, "sent_http_", 10) == 0) {
462 if (ngx_http_variable_unknown_header_out(r
, vv
, (uintptr_t) name
)
471 if (ngx_strncmp(name
->data
, "upstream_http_", 10) == 0) {
473 if (ngx_http_upstream_header_variable(r
, vv
, (uintptr_t) name
)
482 if (ngx_strncmp(name
->data
, "arg_", 4) == 0) {
484 if (ngx_http_variable_argument(r
, vv
, (uintptr_t) name
) == NGX_OK
) {
494 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
495 "unknown \"%V\" variable", name
);
503 ngx_http_variable_request(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
508 s
= (ngx_str_t
*) ((char *) r
+ data
);
526 ngx_http_variable_request_set(ngx_http_request_t
*r
,
527 ngx_http_variable_value_t
*v
, uintptr_t data
)
531 s
= (ngx_str_t
*) ((char *) r
+ data
);
539 ngx_http_variable_request_set_size(ngx_http_request_t
*r
,
540 ngx_http_variable_value_t
*v
, uintptr_t data
)
548 s
= ngx_parse_size(&val
);
550 if (s
== NGX_ERROR
) {
551 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
552 "invalid size \"%V\"", &val
);
556 sp
= (ssize_t
*) ((char *) r
+ data
);
565 ngx_http_variable_header(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
570 h
= *(ngx_table_elt_t
**) ((char *) r
+ data
);
573 v
->len
= h
->value
.len
;
577 v
->data
= h
->value
.data
;
588 ngx_http_variable_headers(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
597 a
= (ngx_array_t
*) ((char *) r
+ data
);
613 v
->len
= (*h
)->value
.len
;
614 v
->data
= (*h
)->value
.data
;
619 len
= - (ssize_t
) (sizeof("; ") - 1);
621 for (i
= 0; i
< n
; i
++) {
622 len
+= h
[i
]->value
.len
+ sizeof("; ") - 1;
625 p
= ngx_pnalloc(r
->pool
, len
);
633 for (i
= 0; /* void */ ; i
++) {
634 p
= ngx_copy(p
, h
[i
]->value
.data
, h
[i
]->value
.len
);
640 *p
++ = ';'; *p
++ = ' ';
648 ngx_http_variable_unknown_header_in(ngx_http_request_t
*r
,
649 ngx_http_variable_value_t
*v
, uintptr_t data
)
651 return ngx_http_variable_unknown_header(v
, (ngx_str_t
*) data
,
652 &r
->headers_in
.headers
.part
,
653 sizeof("http_") - 1);
658 ngx_http_variable_unknown_header_out(ngx_http_request_t
*r
,
659 ngx_http_variable_value_t
*v
, uintptr_t data
)
661 return ngx_http_variable_unknown_header(v
, (ngx_str_t
*) data
,
662 &r
->headers_out
.headers
.part
,
663 sizeof("sent_http_") - 1);
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
)
673 ngx_table_elt_t
*header
;
677 for (i
= 0; /* void */ ; i
++) {
679 if (i
>= part
->nelts
) {
680 if (part
->next
== NULL
) {
689 for (n
= 0; n
+ prefix
< var
->len
&& n
< header
[i
].key
.len
; n
++) {
690 ch
= header
[i
].key
.data
[n
];
692 if (ch
>= 'A' && ch
<= 'Z') {
695 } else if (ch
== '-') {
699 if (var
->data
[n
+ prefix
] != ch
) {
704 if (n
+ prefix
== var
->len
&& n
== header
[i
].key
.len
) {
705 v
->len
= header
[i
].value
.len
;
709 v
->data
= header
[i
].value
.data
;
722 ngx_http_variable_argument(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
725 ngx_str_t
*name
= (ngx_str_t
*) data
;
730 if (r
->args
.len
== 0) {
735 len
= name
->len
- 1 - (sizeof("arg_") - 1);
736 arg
= name
->data
+ sizeof("arg_") - 1;
738 for (p
= r
->args
.data
; *p
&& *p
!= ' '; p
++) {
741 * although r->args.data is not null-terminated by itself,
742 * however, there is null in the end of request line
745 p
= ngx_strcasestrn(p
, (char *) arg
, len
);
752 if ((p
== r
->args
.data
|| *(p
- 1) == '&') && *(p
+ len
+ 1) == '=') {
754 v
->data
= p
+ len
+ 2;
756 p
= (u_char
*) ngx_strchr(p
, '&');
759 p
= r
->args
.data
+ r
->args
.len
;
762 v
->len
= p
- v
->data
;
778 ngx_http_variable_host(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
781 ngx_http_core_srv_conf_t
*cscf
;
783 if (r
->headers_in
.server
.len
) {
784 v
->len
= r
->headers_in
.server
.len
;
785 v
->data
= r
->headers_in
.server
.data
;
788 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
790 v
->len
= cscf
->server_name
.len
;
791 v
->data
= cscf
->server_name
.data
;
803 ngx_http_variable_binary_remote_addr(ngx_http_request_t
*r
,
804 ngx_http_variable_value_t
*v
, uintptr_t data
)
806 struct sockaddr_in
*sin
;
810 sin
= (struct sockaddr_in
*) r
->connection
->sockaddr
;
812 v
->len
= sizeof(in_addr_t
);
816 v
->data
= (u_char
*) &sin
->sin_addr
.s_addr
;
823 ngx_http_variable_remote_addr(ngx_http_request_t
*r
,
824 ngx_http_variable_value_t
*v
, uintptr_t data
)
826 v
->len
= r
->connection
->addr_text
.len
;
830 v
->data
= r
->connection
->addr_text
.data
;
837 ngx_http_variable_remote_port(ngx_http_request_t
*r
,
838 ngx_http_variable_value_t
*v
, uintptr_t data
)
841 struct sockaddr_in
*sin
;
848 v
->data
= ngx_pnalloc(r
->pool
, sizeof("65535") - 1);
849 if (v
->data
== NULL
) {
855 if (r
->connection
->sockaddr
->sa_family
== AF_INET
) {
856 sin
= (struct sockaddr_in
*) r
->connection
->sockaddr
;
858 port
= ntohs(sin
->sin_port
);
860 if (port
> 0 && port
< 65536) {
861 v
->len
= ngx_sprintf(v
->data
, "%ui", port
) - v
->data
;
870 ngx_http_variable_server_addr(ngx_http_request_t
*r
,
871 ngx_http_variable_value_t
*v
, uintptr_t data
)
875 s
.data
= ngx_pnalloc(r
->pool
, INET_ADDRSTRLEN
);
876 if (s
.data
== NULL
) {
880 if (ngx_http_server_addr(r
, &s
) != NGX_OK
) {
895 ngx_http_variable_server_port(ngx_http_request_t
*r
,
896 ngx_http_variable_value_t
*v
, uintptr_t data
)
898 v
->len
= r
->port_text
->len
- 1;
902 v
->data
= r
->port_text
->data
+ 1;
909 ngx_http_variable_scheme(ngx_http_request_t
*r
,
910 ngx_http_variable_value_t
*v
, uintptr_t data
)
914 if (r
->connection
->ssl
) {
915 v
->len
= sizeof("https") - 1;
919 v
->data
= (u_char
*) "https";
926 v
->len
= sizeof("http") - 1;
930 v
->data
= (u_char
*) "http";
937 ngx_http_variable_is_args(ngx_http_request_t
*r
,
938 ngx_http_variable_value_t
*v
, uintptr_t data
)
944 if (r
->args
.len
== 0) {
951 v
->data
= (u_char
*) "?";
958 ngx_http_variable_document_root(ngx_http_request_t
*r
,
959 ngx_http_variable_value_t
*v
, uintptr_t data
)
962 ngx_http_core_loc_conf_t
*clcf
;
964 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
966 if (clcf
->root_lengths
== NULL
) {
967 v
->len
= clcf
->root
.len
;
971 v
->data
= clcf
->root
.data
;
974 if (ngx_http_script_run(r
, &path
, clcf
->root_lengths
->elts
, 0,
975 clcf
->root_values
->elts
)
981 if (ngx_conf_full_name((ngx_cycle_t
*) ngx_cycle
, &path
, 0)
999 ngx_http_variable_request_filename(ngx_http_request_t
*r
,
1000 ngx_http_variable_value_t
*v
, uintptr_t data
)
1005 if (ngx_http_map_uri_to_path(r
, &path
, &root
, 0) == NULL
) {
1009 /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */
1011 v
->len
= path
.len
- 1;
1013 v
->no_cacheable
= 0;
1015 v
->data
= path
.data
;
1022 ngx_http_variable_server_name(ngx_http_request_t
*r
,
1023 ngx_http_variable_value_t
*v
, uintptr_t data
)
1025 ngx_http_core_srv_conf_t
*cscf
;
1027 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
1029 v
->len
= cscf
->server_name
.len
;
1031 v
->no_cacheable
= 0;
1033 v
->data
= cscf
->server_name
.data
;
1040 ngx_http_variable_request_method(ngx_http_request_t
*r
,
1041 ngx_http_variable_value_t
*v
, uintptr_t data
)
1043 if (r
->main
->method_name
.data
) {
1044 v
->len
= r
->main
->method_name
.len
;
1046 v
->no_cacheable
= 0;
1048 v
->data
= r
->main
->method_name
.data
;
1059 ngx_http_variable_remote_user(ngx_http_request_t
*r
,
1060 ngx_http_variable_value_t
*v
, uintptr_t data
)
1064 rc
= ngx_http_auth_basic_user(r
);
1066 if (rc
== NGX_DECLINED
) {
1071 if (rc
== NGX_ERROR
) {
1075 v
->len
= r
->headers_in
.user
.len
;
1077 v
->no_cacheable
= 0;
1079 v
->data
= r
->headers_in
.user
.data
;
1086 ngx_http_variable_body_bytes_sent(ngx_http_request_t
*r
,
1087 ngx_http_variable_value_t
*v
, uintptr_t data
)
1092 sent
= r
->connection
->sent
- r
->header_size
;
1098 p
= ngx_pnalloc(r
->pool
, NGX_OFF_T_LEN
);
1103 v
->len
= ngx_sprintf(p
, "%O", sent
) - p
;
1105 v
->no_cacheable
= 0;
1114 ngx_http_variable_sent_content_type(ngx_http_request_t
*r
,
1115 ngx_http_variable_value_t
*v
, uintptr_t data
)
1117 if (r
->headers_out
.content_type
.len
) {
1118 v
->len
= r
->headers_out
.content_type
.len
;
1120 v
->no_cacheable
= 0;
1122 v
->data
= r
->headers_out
.content_type
.data
;
1133 ngx_http_variable_sent_content_length(ngx_http_request_t
*r
,
1134 ngx_http_variable_value_t
*v
, uintptr_t data
)
1138 if (r
->headers_out
.content_length
) {
1139 v
->len
= r
->headers_out
.content_length
->value
.len
;
1141 v
->no_cacheable
= 0;
1143 v
->data
= r
->headers_out
.content_length
->value
.data
;
1148 if (r
->headers_out
.content_length_n
>= 0) {
1149 p
= ngx_pnalloc(r
->pool
, NGX_OFF_T_LEN
);
1154 v
->len
= ngx_sprintf(p
, "%O", r
->headers_out
.content_length_n
) - p
;
1156 v
->no_cacheable
= 0;
1170 ngx_http_variable_sent_last_modified(ngx_http_request_t
*r
,
1171 ngx_http_variable_value_t
*v
, uintptr_t data
)
1175 if (r
->headers_out
.last_modified
) {
1176 v
->len
= r
->headers_out
.last_modified
->value
.len
;
1178 v
->no_cacheable
= 0;
1180 v
->data
= r
->headers_out
.last_modified
->value
.data
;
1185 if (r
->headers_out
.last_modified_time
>= 0) {
1186 p
= ngx_pnalloc(r
->pool
,
1187 sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT") - 1);
1192 v
->len
= ngx_http_time(p
, r
->headers_out
.last_modified_time
) - p
;
1194 v
->no_cacheable
= 0;
1208 ngx_http_variable_sent_connection(ngx_http_request_t
*r
,
1209 ngx_http_variable_value_t
*v
, uintptr_t data
)
1215 len
= sizeof("keep-alive") - 1;
1219 len
= sizeof("close") - 1;
1225 v
->no_cacheable
= 0;
1227 v
->data
= (u_char
*) p
;
1234 ngx_http_variable_sent_keep_alive(ngx_http_request_t
*r
,
1235 ngx_http_variable_value_t
*v
, uintptr_t data
)
1238 ngx_http_core_loc_conf_t
*clcf
;
1241 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1243 if (clcf
->keepalive_header
) {
1245 p
= ngx_pnalloc(r
->pool
, sizeof("timeout=") - 1 + NGX_TIME_T_LEN
);
1250 v
->len
= ngx_sprintf(p
, "timeout=%T", clcf
->keepalive_header
) - p
;
1252 v
->no_cacheable
= 0;
1267 ngx_http_variable_sent_transfer_encoding(ngx_http_request_t
*r
,
1268 ngx_http_variable_value_t
*v
, uintptr_t data
)
1271 v
->len
= sizeof("chunked") - 1;
1273 v
->no_cacheable
= 0;
1275 v
->data
= (u_char
*) "chunked";
1286 ngx_http_variable_request_completion(ngx_http_request_t
*r
,
1287 ngx_http_variable_value_t
*v
, uintptr_t data
)
1289 if (r
->request_complete
) {
1292 v
->no_cacheable
= 0;
1294 v
->data
= (u_char
*) "OK";
1301 v
->no_cacheable
= 0;
1303 v
->data
= (u_char
*) "";
1310 ngx_http_variable_request_body_file(ngx_http_request_t
*r
,
1311 ngx_http_variable_value_t
*v
, uintptr_t data
)
1313 if (r
->request_body
== NULL
|| r
->request_body
->temp_file
== NULL
) {
1319 v
->len
= r
->request_body
->temp_file
->file
.name
.len
;
1321 v
->no_cacheable
= 0;
1323 v
->data
= r
->request_body
->temp_file
->file
.name
.data
;
1330 ngx_http_variable_nginx_version(ngx_http_request_t
*r
,
1331 ngx_http_variable_value_t
*v
, uintptr_t data
)
1333 v
->len
= sizeof(NGINX_VERSION
) - 1;
1335 v
->no_cacheable
= 0;
1337 v
->data
= (u_char
*) NGINX_VERSION
;
1344 ngx_http_variable_hostname(ngx_http_request_t
*r
,
1345 ngx_http_variable_value_t
*v
, uintptr_t data
)
1347 v
->len
= ngx_cycle
->hostname
.len
;
1349 v
->no_cacheable
= 0;
1351 v
->data
= ngx_cycle
->hostname
.data
;
1358 ngx_http_variables_add_core_vars(ngx_conf_t
*cf
)
1361 ngx_http_variable_t
*v
;
1362 ngx_http_core_main_conf_t
*cmcf
;
1364 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
1366 cmcf
->variables_keys
= ngx_pcalloc(cf
->temp_pool
,
1367 sizeof(ngx_hash_keys_arrays_t
));
1368 if (cmcf
->variables_keys
== NULL
) {
1372 cmcf
->variables_keys
->pool
= cf
->pool
;
1373 cmcf
->variables_keys
->temp_pool
= cf
->pool
;
1375 if (ngx_hash_keys_array_init(cmcf
->variables_keys
, NGX_HASH_SMALL
)
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
);
1389 if (rc
== NGX_BUSY
) {
1390 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
1391 "conflicting variable name \"%V\"", &v
->name
);
1402 ngx_http_variables_init_vars(ngx_conf_t
*cf
)
1405 ngx_hash_key_t
*key
;
1406 ngx_hash_init_t hash
;
1407 ngx_http_variable_t
*v
, *av
;
1408 ngx_http_core_main_conf_t
*cmcf
;
1410 /* set the handlers for the indexed http variables */
1412 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
1414 v
= cmcf
->variables
.elts
;
1415 key
= cmcf
->variables_keys
->keys
.elts
;
1417 for (i
= 0; i
< cmcf
->variables
.nelts
; i
++) {
1419 for (n
= 0; n
< cmcf
->variables_keys
->keys
.nelts
; n
++) {
1424 && v
[i
].name
.len
== key
[n
].key
.len
1425 && ngx_strncmp(v
[i
].name
.data
, key
[n
].key
.data
, v
[i
].name
.len
)
1428 v
[i
].get_handler
= av
->get_handler
;
1429 v
[i
].data
= av
->data
;
1431 av
->flags
|= NGX_HTTP_VAR_INDEXED
;
1432 v
[i
].flags
= av
->flags
;
1440 if (ngx_strncmp(v
[i
].name
.data
, "http_", 5) == 0) {
1441 v
[i
].get_handler
= ngx_http_variable_unknown_header_in
;
1442 v
[i
].data
= (uintptr_t) &v
[i
].name
;
1447 if (ngx_strncmp(v
[i
].name
.data
, "sent_http_", 10) == 0) {
1448 v
[i
].get_handler
= ngx_http_variable_unknown_header_out
;
1449 v
[i
].data
= (uintptr_t) &v
[i
].name
;
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
;
1457 v
[i
].flags
= NGX_HTTP_VAR_NOCACHEABLE
;
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
;
1469 ngx_log_error(NGX_LOG_EMERG
, cf
->log
, 0,
1470 "unknown \"%V\" variable", &v
[i
].name
);
1479 for (n
= 0; n
< cmcf
->variables_keys
->keys
.nelts
; n
++) {
1482 if (av
->flags
& NGX_HTTP_VAR_NOHASH
) {
1483 key
[n
].key
.data
= NULL
;
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
;
1496 if (ngx_hash_init(&hash
, cmcf
->variables_keys
->keys
.elts
,
1497 cmcf
->variables_keys
->keys
.nelts
)
1503 cmcf
->variables_keys
= NULL
;