3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #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 ngx_int_t
ngx_http_variable_request_get_size(ngx_http_request_t
*r
,
19 ngx_http_variable_value_t
*v
, uintptr_t data
);
20 static void ngx_http_variable_request_set_size(ngx_http_request_t
*r
,
21 ngx_http_variable_value_t
*v
, uintptr_t data
);
22 static ngx_int_t
ngx_http_variable_header(ngx_http_request_t
*r
,
23 ngx_http_variable_value_t
*v
, uintptr_t data
);
25 static ngx_int_t
ngx_http_variable_cookies(ngx_http_request_t
*r
,
26 ngx_http_variable_value_t
*v
, uintptr_t data
);
27 static ngx_int_t
ngx_http_variable_headers(ngx_http_request_t
*r
,
28 ngx_http_variable_value_t
*v
, uintptr_t data
);
29 static ngx_int_t
ngx_http_variable_headers_internal(ngx_http_request_t
*r
,
30 ngx_http_variable_value_t
*v
, uintptr_t data
, u_char sep
);
32 static ngx_int_t
ngx_http_variable_unknown_header_in(ngx_http_request_t
*r
,
33 ngx_http_variable_value_t
*v
, uintptr_t data
);
34 static ngx_int_t
ngx_http_variable_unknown_header_out(ngx_http_request_t
*r
,
35 ngx_http_variable_value_t
*v
, uintptr_t data
);
36 static ngx_int_t
ngx_http_variable_request_line(ngx_http_request_t
*r
,
37 ngx_http_variable_value_t
*v
, uintptr_t data
);
38 static ngx_int_t
ngx_http_variable_cookie(ngx_http_request_t
*r
,
39 ngx_http_variable_value_t
*v
, uintptr_t data
);
40 static ngx_int_t
ngx_http_variable_argument(ngx_http_request_t
*r
,
41 ngx_http_variable_value_t
*v
, uintptr_t data
);
42 #if (NGX_HAVE_TCP_INFO)
43 static ngx_int_t
ngx_http_variable_tcpinfo(ngx_http_request_t
*r
,
44 ngx_http_variable_value_t
*v
, uintptr_t data
);
47 static ngx_int_t
ngx_http_variable_content_length(ngx_http_request_t
*r
,
48 ngx_http_variable_value_t
*v
, uintptr_t data
);
49 static ngx_int_t
ngx_http_variable_host(ngx_http_request_t
*r
,
50 ngx_http_variable_value_t
*v
, uintptr_t data
);
51 static ngx_int_t
ngx_http_variable_binary_remote_addr(ngx_http_request_t
*r
,
52 ngx_http_variable_value_t
*v
, uintptr_t data
);
53 static ngx_int_t
ngx_http_variable_remote_addr(ngx_http_request_t
*r
,
54 ngx_http_variable_value_t
*v
, uintptr_t data
);
55 static ngx_int_t
ngx_http_variable_remote_port(ngx_http_request_t
*r
,
56 ngx_http_variable_value_t
*v
, uintptr_t data
);
57 static ngx_int_t
ngx_http_variable_server_addr(ngx_http_request_t
*r
,
58 ngx_http_variable_value_t
*v
, uintptr_t data
);
59 static ngx_int_t
ngx_http_variable_server_port(ngx_http_request_t
*r
,
60 ngx_http_variable_value_t
*v
, uintptr_t data
);
61 static ngx_int_t
ngx_http_variable_scheme(ngx_http_request_t
*r
,
62 ngx_http_variable_value_t
*v
, uintptr_t data
);
63 static ngx_int_t
ngx_http_variable_https(ngx_http_request_t
*r
,
64 ngx_http_variable_value_t
*v
, uintptr_t data
);
65 static ngx_int_t
ngx_http_variable_is_args(ngx_http_request_t
*r
,
66 ngx_http_variable_value_t
*v
, uintptr_t data
);
67 static ngx_int_t
ngx_http_variable_document_root(ngx_http_request_t
*r
,
68 ngx_http_variable_value_t
*v
, uintptr_t data
);
69 static ngx_int_t
ngx_http_variable_realpath_root(ngx_http_request_t
*r
,
70 ngx_http_variable_value_t
*v
, uintptr_t data
);
71 static ngx_int_t
ngx_http_variable_request_filename(ngx_http_request_t
*r
,
72 ngx_http_variable_value_t
*v
, uintptr_t data
);
73 static ngx_int_t
ngx_http_variable_server_name(ngx_http_request_t
*r
,
74 ngx_http_variable_value_t
*v
, uintptr_t data
);
75 static ngx_int_t
ngx_http_variable_request_method(ngx_http_request_t
*r
,
76 ngx_http_variable_value_t
*v
, uintptr_t data
);
77 static ngx_int_t
ngx_http_variable_remote_user(ngx_http_request_t
*r
,
78 ngx_http_variable_value_t
*v
, uintptr_t data
);
79 static ngx_int_t
ngx_http_variable_bytes_sent(ngx_http_request_t
*r
,
80 ngx_http_variable_value_t
*v
, uintptr_t data
);
81 static ngx_int_t
ngx_http_variable_body_bytes_sent(ngx_http_request_t
*r
,
82 ngx_http_variable_value_t
*v
, uintptr_t data
);
83 static ngx_int_t
ngx_http_variable_pipe(ngx_http_request_t
*r
,
84 ngx_http_variable_value_t
*v
, uintptr_t data
);
85 static ngx_int_t
ngx_http_variable_request_completion(ngx_http_request_t
*r
,
86 ngx_http_variable_value_t
*v
, uintptr_t data
);
87 static ngx_int_t
ngx_http_variable_request_body(ngx_http_request_t
*r
,
88 ngx_http_variable_value_t
*v
, uintptr_t data
);
89 static ngx_int_t
ngx_http_variable_request_body_file(ngx_http_request_t
*r
,
90 ngx_http_variable_value_t
*v
, uintptr_t data
);
91 static ngx_int_t
ngx_http_variable_request_length(ngx_http_request_t
*r
,
92 ngx_http_variable_value_t
*v
, uintptr_t data
);
93 static ngx_int_t
ngx_http_variable_request_time(ngx_http_request_t
*r
,
94 ngx_http_variable_value_t
*v
, uintptr_t data
);
95 static ngx_int_t
ngx_http_variable_status(ngx_http_request_t
*r
,
96 ngx_http_variable_value_t
*v
, uintptr_t data
);
98 static ngx_int_t
ngx_http_variable_sent_content_type(ngx_http_request_t
*r
,
99 ngx_http_variable_value_t
*v
, uintptr_t data
);
100 static ngx_int_t
ngx_http_variable_sent_content_length(ngx_http_request_t
*r
,
101 ngx_http_variable_value_t
*v
, uintptr_t data
);
102 static ngx_int_t
ngx_http_variable_sent_location(ngx_http_request_t
*r
,
103 ngx_http_variable_value_t
*v
, uintptr_t data
);
104 static ngx_int_t
ngx_http_variable_sent_last_modified(ngx_http_request_t
*r
,
105 ngx_http_variable_value_t
*v
, uintptr_t data
);
106 static ngx_int_t
ngx_http_variable_sent_connection(ngx_http_request_t
*r
,
107 ngx_http_variable_value_t
*v
, uintptr_t data
);
108 static ngx_int_t
ngx_http_variable_sent_keep_alive(ngx_http_request_t
*r
,
109 ngx_http_variable_value_t
*v
, uintptr_t data
);
110 static ngx_int_t
ngx_http_variable_sent_transfer_encoding(ngx_http_request_t
*r
,
111 ngx_http_variable_value_t
*v
, uintptr_t data
);
113 static ngx_int_t
ngx_http_variable_connection(ngx_http_request_t
*r
,
114 ngx_http_variable_value_t
*v
, uintptr_t data
);
115 static ngx_int_t
ngx_http_variable_connection_requests(ngx_http_request_t
*r
,
116 ngx_http_variable_value_t
*v
, uintptr_t data
);
118 static ngx_int_t
ngx_http_variable_nginx_version(ngx_http_request_t
*r
,
119 ngx_http_variable_value_t
*v
, uintptr_t data
);
120 static ngx_int_t
ngx_http_variable_hostname(ngx_http_request_t
*r
,
121 ngx_http_variable_value_t
*v
, uintptr_t data
);
122 static ngx_int_t
ngx_http_variable_pid(ngx_http_request_t
*r
,
123 ngx_http_variable_value_t
*v
, uintptr_t data
);
124 static ngx_int_t
ngx_http_variable_msec(ngx_http_request_t
*r
,
125 ngx_http_variable_value_t
*v
, uintptr_t data
);
126 static ngx_int_t
ngx_http_variable_time_iso8601(ngx_http_request_t
*r
,
127 ngx_http_variable_value_t
*v
, uintptr_t data
);
128 static ngx_int_t
ngx_http_variable_time_local(ngx_http_request_t
*r
,
129 ngx_http_variable_value_t
*v
, uintptr_t data
);
133 * Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED
134 * REMOTE_HOST (null), REMOTE_IDENT (null),
137 * Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner)
141 * the $http_host, $http_user_agent, $http_referer, and $http_via
142 * variables may be handled by generic
143 * ngx_http_variable_unknown_header_in(), but for performance reasons
144 * they are handled using dedicated entries
147 static ngx_http_variable_t ngx_http_core_variables
[] = {
149 { ngx_string("http_host"), NULL
, ngx_http_variable_header
,
150 offsetof(ngx_http_request_t
, headers_in
.host
), 0, 0 },
152 { ngx_string("http_user_agent"), NULL
, ngx_http_variable_header
,
153 offsetof(ngx_http_request_t
, headers_in
.user_agent
), 0, 0 },
155 { ngx_string("http_referer"), NULL
, ngx_http_variable_header
,
156 offsetof(ngx_http_request_t
, headers_in
.referer
), 0, 0 },
159 { ngx_string("http_via"), NULL
, ngx_http_variable_header
,
160 offsetof(ngx_http_request_t
, headers_in
.via
), 0, 0 },
163 #if (NGX_HTTP_X_FORWARDED_FOR)
164 { ngx_string("http_x_forwarded_for"), NULL
, ngx_http_variable_headers
,
165 offsetof(ngx_http_request_t
, headers_in
.x_forwarded_for
), 0, 0 },
168 { ngx_string("http_cookie"), NULL
, ngx_http_variable_cookies
,
169 offsetof(ngx_http_request_t
, headers_in
.cookies
), 0, 0 },
171 { ngx_string("content_length"), NULL
, ngx_http_variable_content_length
,
174 { ngx_string("content_type"), NULL
, ngx_http_variable_header
,
175 offsetof(ngx_http_request_t
, headers_in
.content_type
), 0, 0 },
177 { ngx_string("host"), NULL
, ngx_http_variable_host
, 0, 0, 0 },
179 { ngx_string("binary_remote_addr"), NULL
,
180 ngx_http_variable_binary_remote_addr
, 0, 0, 0 },
182 { ngx_string("remote_addr"), NULL
, ngx_http_variable_remote_addr
, 0, 0, 0 },
184 { ngx_string("remote_port"), NULL
, ngx_http_variable_remote_port
, 0, 0, 0 },
186 { ngx_string("server_addr"), NULL
, ngx_http_variable_server_addr
, 0, 0, 0 },
188 { ngx_string("server_port"), NULL
, ngx_http_variable_server_port
, 0, 0, 0 },
190 { ngx_string("server_protocol"), NULL
, ngx_http_variable_request
,
191 offsetof(ngx_http_request_t
, http_protocol
), 0, 0 },
193 { ngx_string("scheme"), NULL
, ngx_http_variable_scheme
, 0, 0, 0 },
195 { ngx_string("https"), NULL
, ngx_http_variable_https
, 0, 0, 0 },
197 { ngx_string("request_uri"), NULL
, ngx_http_variable_request
,
198 offsetof(ngx_http_request_t
, unparsed_uri
), 0, 0 },
200 { ngx_string("uri"), NULL
, ngx_http_variable_request
,
201 offsetof(ngx_http_request_t
, uri
),
202 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
204 { ngx_string("document_uri"), NULL
, ngx_http_variable_request
,
205 offsetof(ngx_http_request_t
, uri
),
206 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
208 { ngx_string("request"), NULL
, ngx_http_variable_request_line
, 0, 0, 0 },
210 { ngx_string("document_root"), NULL
,
211 ngx_http_variable_document_root
, 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
213 { ngx_string("realpath_root"), NULL
,
214 ngx_http_variable_realpath_root
, 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
216 { ngx_string("query_string"), NULL
, ngx_http_variable_request
,
217 offsetof(ngx_http_request_t
, args
),
218 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
220 { ngx_string("args"),
221 ngx_http_variable_request_set
,
222 ngx_http_variable_request
,
223 offsetof(ngx_http_request_t
, args
),
224 NGX_HTTP_VAR_CHANGEABLE
|NGX_HTTP_VAR_NOCACHEABLE
, 0 },
226 { ngx_string("is_args"), NULL
, ngx_http_variable_is_args
,
227 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
229 { ngx_string("request_filename"), NULL
,
230 ngx_http_variable_request_filename
, 0,
231 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
233 { ngx_string("server_name"), NULL
, ngx_http_variable_server_name
, 0, 0, 0 },
235 { ngx_string("request_method"), NULL
,
236 ngx_http_variable_request_method
, 0,
237 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
239 { ngx_string("remote_user"), NULL
, ngx_http_variable_remote_user
, 0, 0, 0 },
241 { ngx_string("bytes_sent"), NULL
, ngx_http_variable_bytes_sent
,
244 { ngx_string("body_bytes_sent"), NULL
, ngx_http_variable_body_bytes_sent
,
247 { ngx_string("pipe"), NULL
, ngx_http_variable_pipe
,
250 { ngx_string("request_completion"), NULL
,
251 ngx_http_variable_request_completion
,
254 { ngx_string("request_body"), NULL
,
255 ngx_http_variable_request_body
,
258 { ngx_string("request_body_file"), NULL
,
259 ngx_http_variable_request_body_file
,
262 { ngx_string("request_length"), NULL
, ngx_http_variable_request_length
,
263 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
265 { ngx_string("request_time"), NULL
, ngx_http_variable_request_time
,
266 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
268 { ngx_string("status"), NULL
,
269 ngx_http_variable_status
, 0,
270 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
272 { ngx_string("sent_http_content_type"), NULL
,
273 ngx_http_variable_sent_content_type
, 0, 0, 0 },
275 { ngx_string("sent_http_content_length"), NULL
,
276 ngx_http_variable_sent_content_length
, 0, 0, 0 },
278 { ngx_string("sent_http_location"), NULL
,
279 ngx_http_variable_sent_location
, 0, 0, 0 },
281 { ngx_string("sent_http_last_modified"), NULL
,
282 ngx_http_variable_sent_last_modified
, 0, 0, 0 },
284 { ngx_string("sent_http_connection"), NULL
,
285 ngx_http_variable_sent_connection
, 0, 0, 0 },
287 { ngx_string("sent_http_keep_alive"), NULL
,
288 ngx_http_variable_sent_keep_alive
, 0, 0, 0 },
290 { ngx_string("sent_http_transfer_encoding"), NULL
,
291 ngx_http_variable_sent_transfer_encoding
, 0, 0, 0 },
293 { ngx_string("sent_http_cache_control"), NULL
, ngx_http_variable_headers
,
294 offsetof(ngx_http_request_t
, headers_out
.cache_control
), 0, 0 },
296 { ngx_string("limit_rate"), ngx_http_variable_request_set_size
,
297 ngx_http_variable_request_get_size
,
298 offsetof(ngx_http_request_t
, limit_rate
),
299 NGX_HTTP_VAR_CHANGEABLE
|NGX_HTTP_VAR_NOCACHEABLE
, 0 },
301 { ngx_string("connection"), NULL
,
302 ngx_http_variable_connection
, 0, 0, 0 },
304 { ngx_string("connection_requests"), NULL
,
305 ngx_http_variable_connection_requests
, 0, 0, 0 },
307 { ngx_string("nginx_version"), NULL
, ngx_http_variable_nginx_version
,
310 { ngx_string("hostname"), NULL
, ngx_http_variable_hostname
,
313 { ngx_string("pid"), NULL
, ngx_http_variable_pid
,
316 { ngx_string("msec"), NULL
, ngx_http_variable_msec
,
317 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
319 { ngx_string("time_iso8601"), NULL
, ngx_http_variable_time_iso8601
,
320 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
322 { ngx_string("time_local"), NULL
, ngx_http_variable_time_local
,
323 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
325 #if (NGX_HAVE_TCP_INFO)
326 { ngx_string("tcpinfo_rtt"), NULL
, ngx_http_variable_tcpinfo
,
327 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
329 { ngx_string("tcpinfo_rttvar"), NULL
, ngx_http_variable_tcpinfo
,
330 1, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
332 { ngx_string("tcpinfo_snd_cwnd"), NULL
, ngx_http_variable_tcpinfo
,
333 2, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
335 { ngx_string("tcpinfo_rcv_space"), NULL
, ngx_http_variable_tcpinfo
,
336 3, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
339 { ngx_null_string
, NULL
, NULL
, 0, 0, 0 }
343 ngx_http_variable_value_t ngx_http_variable_null_value
=
344 ngx_http_variable("");
345 ngx_http_variable_value_t ngx_http_variable_true_value
=
346 ngx_http_variable("1");
349 ngx_http_variable_t
*
350 ngx_http_add_variable(ngx_conf_t
*cf
, ngx_str_t
*name
, ngx_uint_t flags
)
355 ngx_http_variable_t
*v
;
356 ngx_http_core_main_conf_t
*cmcf
;
358 if (name
->len
== 0) {
359 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
360 "invalid variable name \"$\"");
364 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
366 key
= cmcf
->variables_keys
->keys
.elts
;
367 for (i
= 0; i
< cmcf
->variables_keys
->keys
.nelts
; i
++) {
368 if (name
->len
!= key
[i
].key
.len
369 || ngx_strncasecmp(name
->data
, key
[i
].key
.data
, name
->len
) != 0)
376 if (!(v
->flags
& NGX_HTTP_VAR_CHANGEABLE
)) {
377 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
378 "the duplicate \"%V\" variable", name
);
385 v
= ngx_palloc(cf
->pool
, sizeof(ngx_http_variable_t
));
390 v
->name
.len
= name
->len
;
391 v
->name
.data
= ngx_pnalloc(cf
->pool
, name
->len
);
392 if (v
->name
.data
== NULL
) {
396 ngx_strlow(v
->name
.data
, name
->data
, name
->len
);
398 v
->set_handler
= NULL
;
399 v
->get_handler
= NULL
;
404 rc
= ngx_hash_add_key(cmcf
->variables_keys
, &v
->name
, v
, 0);
406 if (rc
== NGX_ERROR
) {
410 if (rc
== NGX_BUSY
) {
411 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
412 "conflicting variable name \"%V\"", name
);
421 ngx_http_get_variable_index(ngx_conf_t
*cf
, ngx_str_t
*name
)
424 ngx_http_variable_t
*v
;
425 ngx_http_core_main_conf_t
*cmcf
;
427 if (name
->len
== 0) {
428 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
429 "invalid variable name \"$\"");
433 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
435 v
= cmcf
->variables
.elts
;
438 if (ngx_array_init(&cmcf
->variables
, cf
->pool
, 4,
439 sizeof(ngx_http_variable_t
))
446 for (i
= 0; i
< cmcf
->variables
.nelts
; i
++) {
447 if (name
->len
!= v
[i
].name
.len
448 || ngx_strncasecmp(name
->data
, v
[i
].name
.data
, name
->len
) != 0)
457 v
= ngx_array_push(&cmcf
->variables
);
462 v
->name
.len
= name
->len
;
463 v
->name
.data
= ngx_pnalloc(cf
->pool
, name
->len
);
464 if (v
->name
.data
== NULL
) {
468 ngx_strlow(v
->name
.data
, name
->data
, name
->len
);
470 v
->set_handler
= NULL
;
471 v
->get_handler
= NULL
;
474 v
->index
= cmcf
->variables
.nelts
- 1;
480 ngx_http_variable_value_t
*
481 ngx_http_get_indexed_variable(ngx_http_request_t
*r
, ngx_uint_t index
)
483 ngx_http_variable_t
*v
;
484 ngx_http_core_main_conf_t
*cmcf
;
486 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
488 if (cmcf
->variables
.nelts
<= index
) {
489 ngx_log_error(NGX_LOG_ALERT
, r
->connection
->log
, 0,
490 "unknown variable index: %d", index
);
494 if (r
->variables
[index
].not_found
|| r
->variables
[index
].valid
) {
495 return &r
->variables
[index
];
498 v
= cmcf
->variables
.elts
;
500 if (v
[index
].get_handler(r
, &r
->variables
[index
], v
[index
].data
)
503 if (v
[index
].flags
& NGX_HTTP_VAR_NOCACHEABLE
) {
504 r
->variables
[index
].no_cacheable
= 1;
507 return &r
->variables
[index
];
510 r
->variables
[index
].valid
= 0;
511 r
->variables
[index
].not_found
= 1;
517 ngx_http_variable_value_t
*
518 ngx_http_get_flushed_variable(ngx_http_request_t
*r
, ngx_uint_t index
)
520 ngx_http_variable_value_t
*v
;
522 v
= &r
->variables
[index
];
524 if (v
->valid
|| v
->not_found
) {
525 if (!v
->no_cacheable
) {
533 return ngx_http_get_indexed_variable(r
, index
);
537 ngx_http_variable_value_t
*
538 ngx_http_get_variable(ngx_http_request_t
*r
, ngx_str_t
*name
, ngx_uint_t key
)
540 ngx_http_variable_t
*v
;
541 ngx_http_variable_value_t
*vv
;
542 ngx_http_core_main_conf_t
*cmcf
;
544 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
546 v
= ngx_hash_find(&cmcf
->variables_hash
, key
, name
->data
, name
->len
);
549 if (v
->flags
& NGX_HTTP_VAR_INDEXED
) {
550 return ngx_http_get_flushed_variable(r
, v
->index
);
554 vv
= ngx_palloc(r
->pool
, sizeof(ngx_http_variable_value_t
));
556 if (vv
&& v
->get_handler(r
, vv
, v
->data
) == NGX_OK
) {
564 vv
= ngx_palloc(r
->pool
, sizeof(ngx_http_variable_value_t
));
569 if (ngx_strncmp(name
->data
, "http_", 5) == 0) {
571 if (ngx_http_variable_unknown_header_in(r
, vv
, (uintptr_t) name
)
580 if (ngx_strncmp(name
->data
, "sent_http_", 10) == 0) {
582 if (ngx_http_variable_unknown_header_out(r
, vv
, (uintptr_t) name
)
591 if (ngx_strncmp(name
->data
, "upstream_http_", 14) == 0) {
593 if (ngx_http_upstream_header_variable(r
, vv
, (uintptr_t) name
)
602 if (ngx_strncmp(name
->data
, "cookie_", 7) == 0) {
604 if (ngx_http_variable_cookie(r
, vv
, (uintptr_t) name
) == NGX_OK
) {
611 if (ngx_strncmp(name
->data
, "arg_", 4) == 0) {
613 if (ngx_http_variable_argument(r
, vv
, (uintptr_t) name
) == NGX_OK
) {
627 ngx_http_variable_request(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
632 s
= (ngx_str_t
*) ((char *) r
+ data
);
650 ngx_http_variable_request_set(ngx_http_request_t
*r
,
651 ngx_http_variable_value_t
*v
, uintptr_t data
)
655 s
= (ngx_str_t
*) ((char *) r
+ data
);
663 ngx_http_variable_request_get_size(ngx_http_request_t
*r
,
664 ngx_http_variable_value_t
*v
, uintptr_t data
)
668 sp
= (size_t *) ((char *) r
+ data
);
670 v
->data
= ngx_pnalloc(r
->pool
, NGX_SIZE_T_LEN
);
671 if (v
->data
== NULL
) {
675 v
->len
= ngx_sprintf(v
->data
, "%uz", *sp
) - v
->data
;
685 ngx_http_variable_request_set_size(ngx_http_request_t
*r
,
686 ngx_http_variable_value_t
*v
, uintptr_t data
)
694 s
= ngx_parse_size(&val
);
696 if (s
== NGX_ERROR
) {
697 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
698 "invalid size \"%V\"", &val
);
702 sp
= (ssize_t
*) ((char *) r
+ data
);
711 ngx_http_variable_header(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
716 h
= *(ngx_table_elt_t
**) ((char *) r
+ data
);
719 v
->len
= h
->value
.len
;
723 v
->data
= h
->value
.data
;
734 ngx_http_variable_cookies(ngx_http_request_t
*r
,
735 ngx_http_variable_value_t
*v
, uintptr_t data
)
737 return ngx_http_variable_headers_internal(r
, v
, data
, ';');
742 ngx_http_variable_headers(ngx_http_request_t
*r
,
743 ngx_http_variable_value_t
*v
, uintptr_t data
)
745 return ngx_http_variable_headers_internal(r
, v
, data
, ',');
750 ngx_http_variable_headers_internal(ngx_http_request_t
*r
,
751 ngx_http_variable_value_t
*v
, uintptr_t data
, u_char sep
)
759 a
= (ngx_array_t
*) ((char *) r
+ data
);
766 for (i
= 0; i
< n
; i
++) {
768 if (h
[i
]->hash
== 0) {
772 len
+= h
[i
]->value
.len
+ 2;
787 v
->len
= (*h
)->value
.len
;
788 v
->data
= (*h
)->value
.data
;
793 p
= ngx_pnalloc(r
->pool
, len
);
803 for (i
= 0; /* void */ ; i
++) {
805 if (h
[i
]->hash
== 0) {
809 p
= ngx_copy(p
, h
[i
]->value
.data
, h
[i
]->value
.len
);
815 *p
++ = sep
; *p
++ = ' ';
823 ngx_http_variable_unknown_header_in(ngx_http_request_t
*r
,
824 ngx_http_variable_value_t
*v
, uintptr_t data
)
826 return ngx_http_variable_unknown_header(v
, (ngx_str_t
*) data
,
827 &r
->headers_in
.headers
.part
,
828 sizeof("http_") - 1);
833 ngx_http_variable_unknown_header_out(ngx_http_request_t
*r
,
834 ngx_http_variable_value_t
*v
, uintptr_t data
)
836 return ngx_http_variable_unknown_header(v
, (ngx_str_t
*) data
,
837 &r
->headers_out
.headers
.part
,
838 sizeof("sent_http_") - 1);
843 ngx_http_variable_unknown_header(ngx_http_variable_value_t
*v
, ngx_str_t
*var
,
844 ngx_list_part_t
*part
, size_t prefix
)
848 ngx_table_elt_t
*header
;
852 for (i
= 0; /* void */ ; i
++) {
854 if (i
>= part
->nelts
) {
855 if (part
->next
== NULL
) {
864 if (header
[i
].hash
== 0) {
868 for (n
= 0; n
+ prefix
< var
->len
&& n
< header
[i
].key
.len
; n
++) {
869 ch
= header
[i
].key
.data
[n
];
871 if (ch
>= 'A' && ch
<= 'Z') {
874 } else if (ch
== '-') {
878 if (var
->data
[n
+ prefix
] != ch
) {
883 if (n
+ prefix
== var
->len
&& n
== header
[i
].key
.len
) {
884 v
->len
= header
[i
].value
.len
;
888 v
->data
= header
[i
].value
.data
;
901 ngx_http_variable_request_line(ngx_http_request_t
*r
,
902 ngx_http_variable_value_t
*v
, uintptr_t data
)
906 s
= r
->request_line
.data
;
909 s
= r
->request_start
;
916 for (p
= s
; p
< r
->header_in
->last
; p
++) {
917 if (*p
== CR
|| *p
== LF
) {
922 r
->request_line
.len
= p
- s
;
923 r
->request_line
.data
= s
;
926 v
->len
= r
->request_line
.len
;
937 ngx_http_variable_cookie(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
940 ngx_str_t
*name
= (ngx_str_t
*) data
;
944 s
.len
= name
->len
- (sizeof("cookie_") - 1);
945 s
.data
= name
->data
+ sizeof("cookie_") - 1;
947 if (ngx_http_parse_multi_header_lines(&r
->headers_in
.cookies
, &s
, &cookie
)
958 v
->data
= cookie
.data
;
965 ngx_http_variable_argument(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
968 ngx_str_t
*name
= (ngx_str_t
*) data
;
974 len
= name
->len
- (sizeof("arg_") - 1);
975 arg
= name
->data
+ sizeof("arg_") - 1;
977 if (ngx_http_arg(r
, arg
, len
, &value
) != NGX_OK
) {
982 v
->data
= value
.data
;
992 #if (NGX_HAVE_TCP_INFO)
995 ngx_http_variable_tcpinfo(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
1002 len
= sizeof(struct tcp_info
);
1003 if (getsockopt(r
->connection
->fd
, IPPROTO_TCP
, TCP_INFO
, &ti
, &len
) == -1) {
1008 v
->data
= ngx_pnalloc(r
->pool
, NGX_INT32_LEN
);
1009 if (v
->data
== NULL
) {
1015 value
= ti
.tcpi_rtt
;
1019 value
= ti
.tcpi_rttvar
;
1023 value
= ti
.tcpi_snd_cwnd
;
1027 value
= ti
.tcpi_rcv_space
;
1030 /* suppress warning */
1036 v
->len
= ngx_sprintf(v
->data
, "%uD", value
) - v
->data
;
1038 v
->no_cacheable
= 0;
1048 ngx_http_variable_content_length(ngx_http_request_t
*r
,
1049 ngx_http_variable_value_t
*v
, uintptr_t data
)
1053 if (r
->headers_in
.content_length
) {
1054 v
->len
= r
->headers_in
.content_length
->value
.len
;
1055 v
->data
= r
->headers_in
.content_length
->value
.data
;
1057 v
->no_cacheable
= 0;
1060 } else if (r
->headers_in
.content_length_n
>= 0) {
1061 p
= ngx_pnalloc(r
->pool
, NGX_OFF_T_LEN
);
1066 v
->len
= ngx_sprintf(p
, "%O", r
->headers_in
.content_length_n
) - p
;
1069 v
->no_cacheable
= 0;
1081 ngx_http_variable_host(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
1084 ngx_http_core_srv_conf_t
*cscf
;
1086 if (r
->headers_in
.server
.len
) {
1087 v
->len
= r
->headers_in
.server
.len
;
1088 v
->data
= r
->headers_in
.server
.data
;
1091 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
1093 v
->len
= cscf
->server_name
.len
;
1094 v
->data
= cscf
->server_name
.data
;
1098 v
->no_cacheable
= 0;
1106 ngx_http_variable_binary_remote_addr(ngx_http_request_t
*r
,
1107 ngx_http_variable_value_t
*v
, uintptr_t data
)
1109 struct sockaddr_in
*sin
;
1110 #if (NGX_HAVE_INET6)
1111 struct sockaddr_in6
*sin6
;
1114 switch (r
->connection
->sockaddr
->sa_family
) {
1116 #if (NGX_HAVE_INET6)
1118 sin6
= (struct sockaddr_in6
*) r
->connection
->sockaddr
;
1120 v
->len
= sizeof(struct in6_addr
);
1122 v
->no_cacheable
= 0;
1124 v
->data
= sin6
->sin6_addr
.s6_addr
;
1129 default: /* AF_INET */
1130 sin
= (struct sockaddr_in
*) r
->connection
->sockaddr
;
1132 v
->len
= sizeof(in_addr_t
);
1134 v
->no_cacheable
= 0;
1136 v
->data
= (u_char
*) &sin
->sin_addr
;
1146 ngx_http_variable_remote_addr(ngx_http_request_t
*r
,
1147 ngx_http_variable_value_t
*v
, uintptr_t data
)
1149 v
->len
= r
->connection
->addr_text
.len
;
1151 v
->no_cacheable
= 0;
1153 v
->data
= r
->connection
->addr_text
.data
;
1160 ngx_http_variable_remote_port(ngx_http_request_t
*r
,
1161 ngx_http_variable_value_t
*v
, uintptr_t data
)
1164 struct sockaddr_in
*sin
;
1165 #if (NGX_HAVE_INET6)
1166 struct sockaddr_in6
*sin6
;
1171 v
->no_cacheable
= 0;
1174 v
->data
= ngx_pnalloc(r
->pool
, sizeof("65535") - 1);
1175 if (v
->data
== NULL
) {
1179 switch (r
->connection
->sockaddr
->sa_family
) {
1181 #if (NGX_HAVE_INET6)
1183 sin6
= (struct sockaddr_in6
*) r
->connection
->sockaddr
;
1184 port
= ntohs(sin6
->sin6_port
);
1188 default: /* AF_INET */
1189 sin
= (struct sockaddr_in
*) r
->connection
->sockaddr
;
1190 port
= ntohs(sin
->sin_port
);
1194 if (port
> 0 && port
< 65536) {
1195 v
->len
= ngx_sprintf(v
->data
, "%ui", port
) - v
->data
;
1203 ngx_http_variable_server_addr(ngx_http_request_t
*r
,
1204 ngx_http_variable_value_t
*v
, uintptr_t data
)
1207 u_char addr
[NGX_SOCKADDR_STRLEN
];
1209 s
.len
= NGX_SOCKADDR_STRLEN
;
1212 if (ngx_connection_local_sockaddr(r
->connection
, &s
, 0) != NGX_OK
) {
1216 s
.data
= ngx_pnalloc(r
->pool
, s
.len
);
1217 if (s
.data
== NULL
) {
1221 ngx_memcpy(s
.data
, addr
, s
.len
);
1225 v
->no_cacheable
= 0;
1234 ngx_http_variable_server_port(ngx_http_request_t
*r
,
1235 ngx_http_variable_value_t
*v
, uintptr_t data
)
1238 struct sockaddr_in
*sin
;
1239 #if (NGX_HAVE_INET6)
1240 struct sockaddr_in6
*sin6
;
1245 v
->no_cacheable
= 0;
1248 if (ngx_connection_local_sockaddr(r
->connection
, NULL
, 0) != NGX_OK
) {
1252 v
->data
= ngx_pnalloc(r
->pool
, sizeof("65535") - 1);
1253 if (v
->data
== NULL
) {
1257 switch (r
->connection
->local_sockaddr
->sa_family
) {
1259 #if (NGX_HAVE_INET6)
1261 sin6
= (struct sockaddr_in6
*) r
->connection
->local_sockaddr
;
1262 port
= ntohs(sin6
->sin6_port
);
1266 default: /* AF_INET */
1267 sin
= (struct sockaddr_in
*) r
->connection
->local_sockaddr
;
1268 port
= ntohs(sin
->sin_port
);
1272 if (port
> 0 && port
< 65536) {
1273 v
->len
= ngx_sprintf(v
->data
, "%ui", port
) - v
->data
;
1281 ngx_http_variable_scheme(ngx_http_request_t
*r
,
1282 ngx_http_variable_value_t
*v
, uintptr_t data
)
1286 if (r
->connection
->ssl
) {
1287 v
->len
= sizeof("https") - 1;
1289 v
->no_cacheable
= 0;
1291 v
->data
= (u_char
*) "https";
1298 v
->len
= sizeof("http") - 1;
1300 v
->no_cacheable
= 0;
1302 v
->data
= (u_char
*) "http";
1309 ngx_http_variable_https(ngx_http_request_t
*r
,
1310 ngx_http_variable_value_t
*v
, uintptr_t data
)
1314 if (r
->connection
->ssl
) {
1315 v
->len
= sizeof("on") - 1;
1317 v
->no_cacheable
= 0;
1319 v
->data
= (u_char
*) "on";
1326 *v
= ngx_http_variable_null_value
;
1333 ngx_http_variable_is_args(ngx_http_request_t
*r
,
1334 ngx_http_variable_value_t
*v
, uintptr_t data
)
1337 v
->no_cacheable
= 0;
1340 if (r
->args
.len
== 0) {
1347 v
->data
= (u_char
*) "?";
1354 ngx_http_variable_document_root(ngx_http_request_t
*r
,
1355 ngx_http_variable_value_t
*v
, uintptr_t data
)
1358 ngx_http_core_loc_conf_t
*clcf
;
1360 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1362 if (clcf
->root_lengths
== NULL
) {
1363 v
->len
= clcf
->root
.len
;
1365 v
->no_cacheable
= 0;
1367 v
->data
= clcf
->root
.data
;
1370 if (ngx_http_script_run(r
, &path
, clcf
->root_lengths
->elts
, 0,
1371 clcf
->root_values
->elts
)
1377 if (ngx_conf_full_name((ngx_cycle_t
*) ngx_cycle
, &path
, 0) != NGX_OK
) {
1383 v
->no_cacheable
= 0;
1385 v
->data
= path
.data
;
1393 ngx_http_variable_realpath_root(ngx_http_request_t
*r
,
1394 ngx_http_variable_value_t
*v
, uintptr_t data
)
1399 ngx_http_core_loc_conf_t
*clcf
;
1400 #if (NGX_HAVE_MAX_PATH)
1401 u_char buffer
[NGX_MAX_PATH
];
1404 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1406 if (clcf
->root_lengths
== NULL
) {
1410 if (ngx_http_script_run(r
, &path
, clcf
->root_lengths
->elts
, 1,
1411 clcf
->root_values
->elts
)
1417 path
.data
[path
.len
- 1] = '\0';
1419 if (ngx_conf_full_name((ngx_cycle_t
*) ngx_cycle
, &path
, 0) != NGX_OK
) {
1424 #if (NGX_HAVE_MAX_PATH)
1430 real
= ngx_realpath(path
.data
, real
);
1433 ngx_log_error(NGX_LOG_CRIT
, r
->connection
->log
, ngx_errno
,
1434 ngx_realpath_n
" \"%s\" failed", path
.data
);
1438 len
= ngx_strlen(real
);
1440 v
->data
= ngx_pnalloc(r
->pool
, len
);
1441 if (v
->data
== NULL
) {
1442 #if !(NGX_HAVE_MAX_PATH)
1450 v
->no_cacheable
= 0;
1453 ngx_memcpy(v
->data
, real
, len
);
1455 #if !(NGX_HAVE_MAX_PATH)
1464 ngx_http_variable_request_filename(ngx_http_request_t
*r
,
1465 ngx_http_variable_value_t
*v
, uintptr_t data
)
1470 if (ngx_http_map_uri_to_path(r
, &path
, &root
, 0) == NULL
) {
1474 /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */
1476 v
->len
= path
.len
- 1;
1478 v
->no_cacheable
= 0;
1480 v
->data
= path
.data
;
1487 ngx_http_variable_server_name(ngx_http_request_t
*r
,
1488 ngx_http_variable_value_t
*v
, uintptr_t data
)
1490 ngx_http_core_srv_conf_t
*cscf
;
1492 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
1494 v
->len
= cscf
->server_name
.len
;
1496 v
->no_cacheable
= 0;
1498 v
->data
= cscf
->server_name
.data
;
1505 ngx_http_variable_request_method(ngx_http_request_t
*r
,
1506 ngx_http_variable_value_t
*v
, uintptr_t data
)
1508 if (r
->main
->method_name
.data
) {
1509 v
->len
= r
->main
->method_name
.len
;
1511 v
->no_cacheable
= 0;
1513 v
->data
= r
->main
->method_name
.data
;
1524 ngx_http_variable_remote_user(ngx_http_request_t
*r
,
1525 ngx_http_variable_value_t
*v
, uintptr_t data
)
1529 rc
= ngx_http_auth_basic_user(r
);
1531 if (rc
== NGX_DECLINED
) {
1536 if (rc
== NGX_ERROR
) {
1540 v
->len
= r
->headers_in
.user
.len
;
1542 v
->no_cacheable
= 0;
1544 v
->data
= r
->headers_in
.user
.data
;
1551 ngx_http_variable_bytes_sent(ngx_http_request_t
*r
,
1552 ngx_http_variable_value_t
*v
, uintptr_t data
)
1556 p
= ngx_pnalloc(r
->pool
, NGX_OFF_T_LEN
);
1561 v
->len
= ngx_sprintf(p
, "%O", r
->connection
->sent
) - p
;
1563 v
->no_cacheable
= 0;
1572 ngx_http_variable_body_bytes_sent(ngx_http_request_t
*r
,
1573 ngx_http_variable_value_t
*v
, uintptr_t data
)
1578 sent
= r
->connection
->sent
- r
->header_size
;
1584 p
= ngx_pnalloc(r
->pool
, NGX_OFF_T_LEN
);
1589 v
->len
= ngx_sprintf(p
, "%O", sent
) - p
;
1591 v
->no_cacheable
= 0;
1600 ngx_http_variable_pipe(ngx_http_request_t
*r
,
1601 ngx_http_variable_value_t
*v
, uintptr_t data
)
1603 v
->data
= (u_char
*) (r
->pipeline
? "p" : ".");
1606 v
->no_cacheable
= 0;
1614 ngx_http_variable_status(ngx_http_request_t
*r
,
1615 ngx_http_variable_value_t
*v
, uintptr_t data
)
1619 v
->data
= ngx_pnalloc(r
->pool
, NGX_INT_T_LEN
);
1620 if (v
->data
== NULL
) {
1624 if (r
->err_status
) {
1625 status
= r
->err_status
;
1627 } else if (r
->headers_out
.status
) {
1628 status
= r
->headers_out
.status
;
1630 } else if (r
->http_version
== NGX_HTTP_VERSION_9
) {
1637 v
->len
= ngx_sprintf(v
->data
, "%03ui", status
) - v
->data
;
1639 v
->no_cacheable
= 0;
1647 ngx_http_variable_sent_content_type(ngx_http_request_t
*r
,
1648 ngx_http_variable_value_t
*v
, uintptr_t data
)
1650 if (r
->headers_out
.content_type
.len
) {
1651 v
->len
= r
->headers_out
.content_type
.len
;
1653 v
->no_cacheable
= 0;
1655 v
->data
= r
->headers_out
.content_type
.data
;
1666 ngx_http_variable_sent_content_length(ngx_http_request_t
*r
,
1667 ngx_http_variable_value_t
*v
, uintptr_t data
)
1671 if (r
->headers_out
.content_length
) {
1672 v
->len
= r
->headers_out
.content_length
->value
.len
;
1674 v
->no_cacheable
= 0;
1676 v
->data
= r
->headers_out
.content_length
->value
.data
;
1681 if (r
->headers_out
.content_length_n
>= 0) {
1682 p
= ngx_pnalloc(r
->pool
, NGX_OFF_T_LEN
);
1687 v
->len
= ngx_sprintf(p
, "%O", r
->headers_out
.content_length_n
) - p
;
1689 v
->no_cacheable
= 0;
1703 ngx_http_variable_sent_location(ngx_http_request_t
*r
,
1704 ngx_http_variable_value_t
*v
, uintptr_t data
)
1708 if (r
->headers_out
.location
) {
1709 v
->len
= r
->headers_out
.location
->value
.len
;
1711 v
->no_cacheable
= 0;
1713 v
->data
= r
->headers_out
.location
->value
.data
;
1718 ngx_str_set(&name
, "sent_http_location");
1720 return ngx_http_variable_unknown_header(v
, &name
,
1721 &r
->headers_out
.headers
.part
,
1722 sizeof("sent_http_") - 1);
1727 ngx_http_variable_sent_last_modified(ngx_http_request_t
*r
,
1728 ngx_http_variable_value_t
*v
, uintptr_t data
)
1732 if (r
->headers_out
.last_modified
) {
1733 v
->len
= r
->headers_out
.last_modified
->value
.len
;
1735 v
->no_cacheable
= 0;
1737 v
->data
= r
->headers_out
.last_modified
->value
.data
;
1742 if (r
->headers_out
.last_modified_time
>= 0) {
1743 p
= ngx_pnalloc(r
->pool
,
1744 sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT") - 1);
1749 v
->len
= ngx_http_time(p
, r
->headers_out
.last_modified_time
) - p
;
1751 v
->no_cacheable
= 0;
1765 ngx_http_variable_sent_connection(ngx_http_request_t
*r
,
1766 ngx_http_variable_value_t
*v
, uintptr_t data
)
1771 if (r
->headers_out
.status
== NGX_HTTP_SWITCHING_PROTOCOLS
) {
1772 len
= sizeof("upgrade") - 1;
1775 } else if (r
->keepalive
) {
1776 len
= sizeof("keep-alive") - 1;
1780 len
= sizeof("close") - 1;
1786 v
->no_cacheable
= 0;
1788 v
->data
= (u_char
*) p
;
1795 ngx_http_variable_sent_keep_alive(ngx_http_request_t
*r
,
1796 ngx_http_variable_value_t
*v
, uintptr_t data
)
1799 ngx_http_core_loc_conf_t
*clcf
;
1802 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1804 if (clcf
->keepalive_header
) {
1806 p
= ngx_pnalloc(r
->pool
, sizeof("timeout=") - 1 + NGX_TIME_T_LEN
);
1811 v
->len
= ngx_sprintf(p
, "timeout=%T", clcf
->keepalive_header
) - p
;
1813 v
->no_cacheable
= 0;
1828 ngx_http_variable_sent_transfer_encoding(ngx_http_request_t
*r
,
1829 ngx_http_variable_value_t
*v
, uintptr_t data
)
1832 v
->len
= sizeof("chunked") - 1;
1834 v
->no_cacheable
= 0;
1836 v
->data
= (u_char
*) "chunked";
1847 ngx_http_variable_request_completion(ngx_http_request_t
*r
,
1848 ngx_http_variable_value_t
*v
, uintptr_t data
)
1850 if (r
->request_complete
) {
1853 v
->no_cacheable
= 0;
1855 v
->data
= (u_char
*) "OK";
1862 v
->no_cacheable
= 0;
1864 v
->data
= (u_char
*) "";
1871 ngx_http_variable_request_body(ngx_http_request_t
*r
,
1872 ngx_http_variable_value_t
*v
, uintptr_t data
)
1879 if (r
->request_body
== NULL
1880 || r
->request_body
->bufs
== NULL
1881 || r
->request_body
->temp_file
)
1888 cl
= r
->request_body
->bufs
;
1891 if (cl
->next
== NULL
) {
1892 v
->len
= buf
->last
- buf
->pos
;
1894 v
->no_cacheable
= 0;
1901 len
= buf
->last
- buf
->pos
;
1904 for ( /* void */ ; cl
; cl
= cl
->next
) {
1906 len
+= buf
->last
- buf
->pos
;
1909 p
= ngx_pnalloc(r
->pool
, len
);
1915 cl
= r
->request_body
->bufs
;
1917 for ( /* void */ ; cl
; cl
= cl
->next
) {
1919 p
= ngx_cpymem(p
, buf
->pos
, buf
->last
- buf
->pos
);
1924 v
->no_cacheable
= 0;
1932 ngx_http_variable_request_body_file(ngx_http_request_t
*r
,
1933 ngx_http_variable_value_t
*v
, uintptr_t data
)
1935 if (r
->request_body
== NULL
|| r
->request_body
->temp_file
== NULL
) {
1941 v
->len
= r
->request_body
->temp_file
->file
.name
.len
;
1943 v
->no_cacheable
= 0;
1945 v
->data
= r
->request_body
->temp_file
->file
.name
.data
;
1952 ngx_http_variable_request_length(ngx_http_request_t
*r
,
1953 ngx_http_variable_value_t
*v
, uintptr_t data
)
1957 p
= ngx_pnalloc(r
->pool
, NGX_OFF_T_LEN
);
1962 v
->len
= ngx_sprintf(p
, "%O", r
->request_length
) - p
;
1964 v
->no_cacheable
= 0;
1973 ngx_http_variable_request_time(ngx_http_request_t
*r
,
1974 ngx_http_variable_value_t
*v
, uintptr_t data
)
1980 p
= ngx_pnalloc(r
->pool
, NGX_TIME_T_LEN
+ 4);
1985 tp
= ngx_timeofday();
1987 ms
= (ngx_msec_int_t
)
1988 ((tp
->sec
- r
->start_sec
) * 1000 + (tp
->msec
- r
->start_msec
));
1989 ms
= ngx_max(ms
, 0);
1991 v
->len
= ngx_sprintf(p
, "%T.%03M", ms
/ 1000, ms
% 1000) - p
;
1993 v
->no_cacheable
= 0;
2002 ngx_http_variable_connection(ngx_http_request_t
*r
,
2003 ngx_http_variable_value_t
*v
, uintptr_t data
)
2007 p
= ngx_pnalloc(r
->pool
, NGX_ATOMIC_T_LEN
);
2012 v
->len
= ngx_sprintf(p
, "%uA", r
->connection
->number
) - p
;
2014 v
->no_cacheable
= 0;
2023 ngx_http_variable_connection_requests(ngx_http_request_t
*r
,
2024 ngx_http_variable_value_t
*v
, uintptr_t data
)
2028 p
= ngx_pnalloc(r
->pool
, NGX_INT_T_LEN
);
2033 v
->len
= ngx_sprintf(p
, "%ui", r
->connection
->requests
) - p
;
2035 v
->no_cacheable
= 0;
2044 ngx_http_variable_nginx_version(ngx_http_request_t
*r
,
2045 ngx_http_variable_value_t
*v
, uintptr_t data
)
2047 v
->len
= sizeof(NGINX_VERSION
) - 1;
2049 v
->no_cacheable
= 0;
2051 v
->data
= (u_char
*) NGINX_VERSION
;
2058 ngx_http_variable_hostname(ngx_http_request_t
*r
,
2059 ngx_http_variable_value_t
*v
, uintptr_t data
)
2061 v
->len
= ngx_cycle
->hostname
.len
;
2063 v
->no_cacheable
= 0;
2065 v
->data
= ngx_cycle
->hostname
.data
;
2072 ngx_http_variable_pid(ngx_http_request_t
*r
,
2073 ngx_http_variable_value_t
*v
, uintptr_t data
)
2077 p
= ngx_pnalloc(r
->pool
, NGX_INT64_LEN
);
2082 v
->len
= ngx_sprintf(p
, "%P", ngx_pid
) - p
;
2084 v
->no_cacheable
= 0;
2093 ngx_http_variable_msec(ngx_http_request_t
*r
,
2094 ngx_http_variable_value_t
*v
, uintptr_t data
)
2099 p
= ngx_pnalloc(r
->pool
, NGX_TIME_T_LEN
+ 4);
2104 tp
= ngx_timeofday();
2106 v
->len
= ngx_sprintf(p
, "%T.%03M", tp
->sec
, tp
->msec
) - p
;
2108 v
->no_cacheable
= 0;
2117 ngx_http_variable_time_iso8601(ngx_http_request_t
*r
,
2118 ngx_http_variable_value_t
*v
, uintptr_t data
)
2122 p
= ngx_pnalloc(r
->pool
, ngx_cached_http_log_iso8601
.len
);
2127 ngx_memcpy(p
, ngx_cached_http_log_iso8601
.data
,
2128 ngx_cached_http_log_iso8601
.len
);
2130 v
->len
= ngx_cached_http_log_iso8601
.len
;
2132 v
->no_cacheable
= 0;
2141 ngx_http_variable_time_local(ngx_http_request_t
*r
,
2142 ngx_http_variable_value_t
*v
, uintptr_t data
)
2146 p
= ngx_pnalloc(r
->pool
, ngx_cached_http_log_time
.len
);
2151 ngx_memcpy(p
, ngx_cached_http_log_time
.data
, ngx_cached_http_log_time
.len
);
2153 v
->len
= ngx_cached_http_log_time
.len
;
2155 v
->no_cacheable
= 0;
2164 ngx_http_map_find(ngx_http_request_t
*r
, ngx_http_map_t
*map
, ngx_str_t
*match
)
2174 low
= ngx_pnalloc(r
->pool
, len
);
2183 key
= ngx_hash_strlow(low
, match
->data
, len
);
2185 value
= ngx_hash_find_combined(&map
->hash
, key
, low
, len
);
2192 if (len
&& map
->nregex
) {
2195 ngx_http_map_regex_t
*reg
;
2199 for (i
= 0; i
< map
->nregex
; i
++) {
2201 n
= ngx_http_regex_exec(r
, reg
[i
].regex
, match
);
2204 return reg
[i
].value
;
2207 if (n
== NGX_DECLINED
) {
2226 ngx_http_variable_not_found(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
2235 ngx_http_regex_compile(ngx_conf_t
*cf
, ngx_regex_compile_t
*rc
)
2241 ngx_http_variable_t
*v
;
2242 ngx_http_regex_t
*re
;
2243 ngx_http_regex_variable_t
*rv
;
2244 ngx_http_core_main_conf_t
*cmcf
;
2246 rc
->pool
= cf
->pool
;
2248 if (ngx_regex_compile(rc
) != NGX_OK
) {
2249 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0, "%V", &rc
->err
);
2253 re
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_regex_t
));
2258 re
->regex
= rc
->regex
;
2259 re
->ncaptures
= rc
->captures
;
2261 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
2262 cmcf
->ncaptures
= ngx_max(cmcf
->ncaptures
, re
->ncaptures
);
2264 n
= (ngx_uint_t
) rc
->named_captures
;
2270 rv
= ngx_palloc(rc
->pool
, n
* sizeof(ngx_http_regex_variable_t
));
2277 re
->name
= rc
->pattern
;
2279 size
= rc
->name_size
;
2282 for (i
= 0; i
< n
; i
++) {
2283 rv
[i
].capture
= 2 * ((p
[0] << 8) + p
[1]);
2286 name
.len
= ngx_strlen(name
.data
);
2288 v
= ngx_http_add_variable(cf
, &name
, NGX_HTTP_VAR_CHANGEABLE
);
2293 rv
[i
].index
= ngx_http_get_variable_index(cf
, &name
);
2294 if (rv
[i
].index
== NGX_ERROR
) {
2298 v
->get_handler
= ngx_http_variable_not_found
;
2308 ngx_http_regex_exec(ngx_http_request_t
*r
, ngx_http_regex_t
*re
, ngx_str_t
*s
)
2310 ngx_int_t rc
, index
;
2311 ngx_uint_t i
, n
, len
;
2312 ngx_http_variable_value_t
*vv
;
2313 ngx_http_core_main_conf_t
*cmcf
;
2315 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
2317 if (re
->ncaptures
) {
2318 len
= cmcf
->ncaptures
;
2320 if (r
->captures
== NULL
) {
2321 r
->captures
= ngx_palloc(r
->pool
, len
* sizeof(int));
2322 if (r
->captures
== NULL
) {
2331 rc
= ngx_regex_exec(re
->regex
, s
, r
->captures
, len
);
2333 if (rc
== NGX_REGEX_NO_MATCHED
) {
2334 return NGX_DECLINED
;
2338 ngx_log_error(NGX_LOG_ALERT
, r
->connection
->log
, 0,
2339 ngx_regex_exec_n
" failed: %i on \"%V\" using \"%V\"",
2344 for (i
= 0; i
< re
->nvariables
; i
++) {
2346 n
= re
->variables
[i
].capture
;
2347 index
= re
->variables
[i
].index
;
2348 vv
= &r
->variables
[index
];
2350 vv
->len
= r
->captures
[n
+ 1] - r
->captures
[n
];
2352 vv
->no_cacheable
= 0;
2354 vv
->data
= &s
->data
[r
->captures
[n
]];
2358 ngx_http_variable_t
*v
;
2360 v
= cmcf
->variables
.elts
;
2362 ngx_log_debug3(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2363 "http regex set $%V to \"%*s\"",
2364 &v
[index
].name
, vv
->len
, vv
->data
);
2369 r
->ncaptures
= rc
* 2;
2370 r
->captures_data
= s
->data
;
2379 ngx_http_variables_add_core_vars(ngx_conf_t
*cf
)
2382 ngx_http_variable_t
*cv
, *v
;
2383 ngx_http_core_main_conf_t
*cmcf
;
2385 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
2387 cmcf
->variables_keys
= ngx_pcalloc(cf
->temp_pool
,
2388 sizeof(ngx_hash_keys_arrays_t
));
2389 if (cmcf
->variables_keys
== NULL
) {
2393 cmcf
->variables_keys
->pool
= cf
->pool
;
2394 cmcf
->variables_keys
->temp_pool
= cf
->pool
;
2396 if (ngx_hash_keys_array_init(cmcf
->variables_keys
, NGX_HASH_SMALL
)
2402 for (cv
= ngx_http_core_variables
; cv
->name
.len
; cv
++) {
2403 v
= ngx_palloc(cf
->pool
, sizeof(ngx_http_variable_t
));
2410 rc
= ngx_hash_add_key(cmcf
->variables_keys
, &v
->name
, v
,
2411 NGX_HASH_READONLY_KEY
);
2417 if (rc
== NGX_BUSY
) {
2418 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2419 "conflicting variable name \"%V\"", &v
->name
);
2430 ngx_http_variables_init_vars(ngx_conf_t
*cf
)
2433 ngx_hash_key_t
*key
;
2434 ngx_hash_init_t hash
;
2435 ngx_http_variable_t
*v
, *av
;
2436 ngx_http_core_main_conf_t
*cmcf
;
2438 /* set the handlers for the indexed http variables */
2440 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
2442 v
= cmcf
->variables
.elts
;
2443 key
= cmcf
->variables_keys
->keys
.elts
;
2445 for (i
= 0; i
< cmcf
->variables
.nelts
; i
++) {
2447 for (n
= 0; n
< cmcf
->variables_keys
->keys
.nelts
; n
++) {
2452 && v
[i
].name
.len
== key
[n
].key
.len
2453 && ngx_strncmp(v
[i
].name
.data
, key
[n
].key
.data
, v
[i
].name
.len
)
2456 v
[i
].get_handler
= av
->get_handler
;
2457 v
[i
].data
= av
->data
;
2459 av
->flags
|= NGX_HTTP_VAR_INDEXED
;
2460 v
[i
].flags
= av
->flags
;
2468 if (ngx_strncmp(v
[i
].name
.data
, "http_", 5) == 0) {
2469 v
[i
].get_handler
= ngx_http_variable_unknown_header_in
;
2470 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2475 if (ngx_strncmp(v
[i
].name
.data
, "sent_http_", 10) == 0) {
2476 v
[i
].get_handler
= ngx_http_variable_unknown_header_out
;
2477 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2482 if (ngx_strncmp(v
[i
].name
.data
, "upstream_http_", 14) == 0) {
2483 v
[i
].get_handler
= ngx_http_upstream_header_variable
;
2484 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2485 v
[i
].flags
= NGX_HTTP_VAR_NOCACHEABLE
;
2490 if (ngx_strncmp(v
[i
].name
.data
, "cookie_", 7) == 0) {
2491 v
[i
].get_handler
= ngx_http_variable_cookie
;
2492 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2497 if (ngx_strncmp(v
[i
].name
.data
, "arg_", 4) == 0) {
2498 v
[i
].get_handler
= ngx_http_variable_argument
;
2499 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2500 v
[i
].flags
= NGX_HTTP_VAR_NOCACHEABLE
;
2505 ngx_log_error(NGX_LOG_EMERG
, cf
->log
, 0,
2506 "unknown \"%V\" variable", &v
[i
].name
);
2515 for (n
= 0; n
< cmcf
->variables_keys
->keys
.nelts
; n
++) {
2518 if (av
->flags
& NGX_HTTP_VAR_NOHASH
) {
2519 key
[n
].key
.data
= NULL
;
2524 hash
.hash
= &cmcf
->variables_hash
;
2525 hash
.key
= ngx_hash_key
;
2526 hash
.max_size
= cmcf
->variables_hash_max_size
;
2527 hash
.bucket_size
= cmcf
->variables_hash_bucket_size
;
2528 hash
.name
= "variables_hash";
2529 hash
.pool
= cf
->pool
;
2530 hash
.temp_pool
= NULL
;
2532 if (ngx_hash_init(&hash
, cmcf
->variables_keys
->keys
.elts
,
2533 cmcf
->variables_keys
->keys
.nelts
)
2539 cmcf
->variables_keys
= NULL
;