3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
16 static ngx_int_t
ngx_http_variable_request(ngx_http_request_t
*r
,
17 ngx_http_variable_value_t
*v
, uintptr_t data
);
18 static void ngx_http_variable_request_set(ngx_http_request_t
*r
,
19 ngx_http_variable_value_t
*v
, uintptr_t data
);
20 static ngx_int_t
ngx_http_variable_request_get_size(ngx_http_request_t
*r
,
21 ngx_http_variable_value_t
*v
, uintptr_t data
);
22 static void ngx_http_variable_request_set_size(ngx_http_request_t
*r
,
23 ngx_http_variable_value_t
*v
, uintptr_t data
);
24 static ngx_int_t
ngx_http_variable_header(ngx_http_request_t
*r
,
25 ngx_http_variable_value_t
*v
, uintptr_t data
);
26 static ngx_int_t
ngx_http_variable_headers(ngx_http_request_t
*r
,
27 ngx_http_variable_value_t
*v
, uintptr_t data
);
29 static ngx_int_t
ngx_http_variable_unknown_header_in(ngx_http_request_t
*r
,
30 ngx_http_variable_value_t
*v
, uintptr_t data
);
31 static ngx_int_t
ngx_http_variable_unknown_header_out(ngx_http_request_t
*r
,
32 ngx_http_variable_value_t
*v
, uintptr_t data
);
33 static ngx_int_t
ngx_http_variable_request_line(ngx_http_request_t
*r
,
34 ngx_http_variable_value_t
*v
, uintptr_t data
);
35 static ngx_int_t
ngx_http_variable_cookie(ngx_http_request_t
*r
,
36 ngx_http_variable_value_t
*v
, uintptr_t data
);
38 static ngx_int_t
ngx_http_variable_ssi(ngx_http_request_t
*r
,
39 ngx_http_variable_value_t
*v
, uintptr_t data
);
41 static ngx_int_t
ngx_http_variable_urlencode(ngx_http_request_t
*r
,
42 ngx_http_variable_value_t
*v
, uintptr_t data
);
43 static ngx_int_t
ngx_http_variable_urldecode(ngx_http_request_t
*r
,
44 ngx_http_variable_value_t
*v
, uintptr_t data
);
45 static ngx_int_t
ngx_http_variable_crc32(ngx_http_request_t
*r
,
46 ngx_http_variable_value_t
*v
, uintptr_t data
);
48 static ngx_int_t
ngx_http_variable_md5(ngx_http_request_t
*r
,
49 ngx_http_variable_value_t
*v
, uintptr_t data
);
51 static ngx_int_t
ngx_http_variable_argument(ngx_http_request_t
*r
,
52 ngx_http_variable_value_t
*v
, uintptr_t data
);
54 static ngx_int_t
ngx_http_variable_host(ngx_http_request_t
*r
,
55 ngx_http_variable_value_t
*v
, uintptr_t data
);
56 static ngx_int_t
ngx_http_variable_binary_remote_addr(ngx_http_request_t
*r
,
57 ngx_http_variable_value_t
*v
, uintptr_t data
);
58 static ngx_int_t
ngx_http_variable_remote_addr(ngx_http_request_t
*r
,
59 ngx_http_variable_value_t
*v
, uintptr_t data
);
60 static ngx_int_t
ngx_http_variable_remote_port(ngx_http_request_t
*r
,
61 ngx_http_variable_value_t
*v
, uintptr_t data
);
62 static ngx_int_t
ngx_http_variable_server_addr(ngx_http_request_t
*r
,
63 ngx_http_variable_value_t
*v
, uintptr_t data
);
64 static ngx_int_t
ngx_http_variable_server_port(ngx_http_request_t
*r
,
65 ngx_http_variable_value_t
*v
, uintptr_t data
);
66 static ngx_int_t
ngx_http_variable_scheme(ngx_http_request_t
*r
,
67 ngx_http_variable_value_t
*v
, uintptr_t data
);
68 static ngx_int_t
ngx_http_variable_is_args(ngx_http_request_t
*r
,
69 ngx_http_variable_value_t
*v
, uintptr_t data
);
70 static ngx_int_t
ngx_http_variable_document_root(ngx_http_request_t
*r
,
71 ngx_http_variable_value_t
*v
, uintptr_t data
);
72 static ngx_int_t
ngx_http_variable_realpath_root(ngx_http_request_t
*r
,
73 ngx_http_variable_value_t
*v
, uintptr_t data
);
74 static ngx_int_t
ngx_http_variable_request_filename(ngx_http_request_t
*r
,
75 ngx_http_variable_value_t
*v
, uintptr_t data
);
76 static ngx_int_t
ngx_http_variable_server_name(ngx_http_request_t
*r
,
77 ngx_http_variable_value_t
*v
, uintptr_t data
);
78 static ngx_int_t
ngx_http_variable_request_method(ngx_http_request_t
*r
,
79 ngx_http_variable_value_t
*v
, uintptr_t data
);
80 static ngx_int_t
ngx_http_variable_remote_user(ngx_http_request_t
*r
,
81 ngx_http_variable_value_t
*v
, uintptr_t data
);
82 static ngx_int_t
ngx_http_variable_body_bytes_sent(ngx_http_request_t
*r
,
83 ngx_http_variable_value_t
*v
, uintptr_t data
);
84 static ngx_int_t
ngx_http_variable_request_completion(ngx_http_request_t
*r
,
85 ngx_http_variable_value_t
*v
, uintptr_t data
);
86 static ngx_int_t
ngx_http_variable_request_body(ngx_http_request_t
*r
,
87 ngx_http_variable_value_t
*v
, uintptr_t data
);
88 static ngx_int_t
ngx_http_variable_request_body_file(ngx_http_request_t
*r
,
89 ngx_http_variable_value_t
*v
, uintptr_t data
);
91 static ngx_int_t
ngx_http_variable_sent_content_type(ngx_http_request_t
*r
,
92 ngx_http_variable_value_t
*v
, uintptr_t data
);
93 static ngx_int_t
ngx_http_variable_sent_content_length(ngx_http_request_t
*r
,
94 ngx_http_variable_value_t
*v
, uintptr_t data
);
95 static ngx_int_t
ngx_http_variable_sent_location(ngx_http_request_t
*r
,
96 ngx_http_variable_value_t
*v
, uintptr_t data
);
97 static ngx_int_t
ngx_http_variable_sent_last_modified(ngx_http_request_t
*r
,
98 ngx_http_variable_value_t
*v
, uintptr_t data
);
99 static ngx_int_t
ngx_http_variable_sent_etag(ngx_http_request_t
*r
,
100 ngx_http_variable_value_t
*v
, uintptr_t data
);
101 static ngx_int_t
ngx_http_variable_sent_connection(ngx_http_request_t
*r
,
102 ngx_http_variable_value_t
*v
, uintptr_t data
);
103 static ngx_int_t
ngx_http_variable_sent_keep_alive(ngx_http_request_t
*r
,
104 ngx_http_variable_value_t
*v
, uintptr_t data
);
105 static ngx_int_t
ngx_http_variable_sent_transfer_encoding(ngx_http_request_t
*r
,
106 ngx_http_variable_value_t
*v
, uintptr_t data
);
108 static ngx_int_t
ngx_http_variable_nginx_version(ngx_http_request_t
*r
,
109 ngx_http_variable_value_t
*v
, uintptr_t data
);
110 static ngx_int_t
ngx_http_variable_hostname(ngx_http_request_t
*r
,
111 ngx_http_variable_value_t
*v
, uintptr_t data
);
112 static ngx_int_t
ngx_http_variable_pid(ngx_http_request_t
*r
,
113 ngx_http_variable_value_t
*v
, uintptr_t data
);
114 static ngx_int_t
ngx_http_variable_timestamp(ngx_http_request_t
*r
,
115 ngx_http_variable_value_t
*v
, uintptr_t data
);
116 static ngx_int_t
ngx_http_variable_mstimestamp(ngx_http_request_t
*r
,
117 ngx_http_variable_value_t
*v
, uintptr_t data
);
118 static ngx_int_t
ngx_http_variable_loadavg_1m(ngx_http_request_t
*r
,
119 ngx_http_variable_value_t
*v
, uintptr_t data
);
120 static ngx_int_t
ngx_http_variable_loadavg_5m(ngx_http_request_t
*r
,
121 ngx_http_variable_value_t
*v
, uintptr_t data
);
122 static ngx_int_t
ngx_http_variable_loadavg_15m(ngx_http_request_t
*r
,
123 ngx_http_variable_value_t
*v
, uintptr_t data
);
127 * Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED
128 * REMOTE_HOST (null), REMOTE_IDENT (null),
131 * Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner)
135 * the $http_host, $http_user_agent, $http_referer, $http_via,
136 * and $http_x_forwarded_for variables may be handled by generic
137 * ngx_http_variable_unknown_header_in(), but for perfomance reasons
138 * they are handled using dedicated entries
141 static ngx_http_variable_t ngx_http_core_variables
[] = {
143 { ngx_string("http_host"), NULL
, ngx_http_variable_header
,
144 offsetof(ngx_http_request_t
, headers_in
.host
), 0, 0 },
146 { ngx_string("http_user_agent"), NULL
, ngx_http_variable_header
,
147 offsetof(ngx_http_request_t
, headers_in
.user_agent
), 0, 0 },
149 { ngx_string("http_referer"), NULL
, ngx_http_variable_header
,
150 offsetof(ngx_http_request_t
, headers_in
.referer
), 0, 0 },
153 { ngx_string("http_via"), NULL
, ngx_http_variable_header
,
154 offsetof(ngx_http_request_t
, headers_in
.via
), 0, 0 },
157 #if (NGX_HTTP_PROXY || NGX_HTTP_REALIP)
158 { ngx_string("http_x_forwarded_for"), NULL
, ngx_http_variable_header
,
159 offsetof(ngx_http_request_t
, headers_in
.x_forwarded_for
), 0, 0 },
162 { ngx_string("http_cookie"), NULL
, ngx_http_variable_headers
,
163 offsetof(ngx_http_request_t
, headers_in
.cookies
), 0, 0 },
165 { ngx_string("content_length"), NULL
, ngx_http_variable_header
,
166 offsetof(ngx_http_request_t
, headers_in
.content_length
), 0, 0 },
168 { ngx_string("content_type"), NULL
, ngx_http_variable_header
,
169 offsetof(ngx_http_request_t
, headers_in
.content_type
), 0, 0 },
171 { ngx_string("host"), NULL
, ngx_http_variable_host
, 0, 0, 0 },
173 { ngx_string("binary_remote_addr"), NULL
,
174 ngx_http_variable_binary_remote_addr
, 0, 0, 0 },
176 { ngx_string("remote_addr"), NULL
, ngx_http_variable_remote_addr
, 0, 0, 0 },
178 { ngx_string("remote_port"), NULL
, ngx_http_variable_remote_port
, 0, 0, 0 },
180 { ngx_string("server_addr"), NULL
, ngx_http_variable_server_addr
, 0, 0, 0 },
182 { ngx_string("server_port"), NULL
, ngx_http_variable_server_port
, 0, 0, 0 },
184 { ngx_string("server_protocol"), NULL
, ngx_http_variable_request
,
185 offsetof(ngx_http_request_t
, http_protocol
), 0, 0 },
187 { ngx_string("scheme"), NULL
, ngx_http_variable_scheme
, 0, 0, 0 },
189 { ngx_string("request_uri"), NULL
, ngx_http_variable_request
,
190 offsetof(ngx_http_request_t
, unparsed_uri
), 0, 0 },
192 { ngx_string("uri"), NULL
, ngx_http_variable_request
,
193 offsetof(ngx_http_request_t
, uri
),
194 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
196 { ngx_string("uri_remainder"), NULL
, ngx_http_variable_request
,
197 offsetof(ngx_http_request_t
, uri_remainder
),
198 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
200 { ngx_string("document_uri"), NULL
, ngx_http_variable_request
,
201 offsetof(ngx_http_request_t
, uri
),
202 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
204 { ngx_string("request"), NULL
, ngx_http_variable_request_line
, 0, 0, 0 },
206 { ngx_string("document_root"), NULL
,
207 ngx_http_variable_document_root
, 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
209 { ngx_string("realpath_root"), NULL
,
210 ngx_http_variable_realpath_root
, 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
212 { ngx_string("query_string"), NULL
, ngx_http_variable_request
,
213 offsetof(ngx_http_request_t
, args
),
214 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
216 { ngx_string("args"),
217 ngx_http_variable_request_set
,
218 ngx_http_variable_request
,
219 offsetof(ngx_http_request_t
, args
),
220 NGX_HTTP_VAR_CHANGEABLE
|NGX_HTTP_VAR_NOCACHEABLE
, 0 },
222 { ngx_string("is_args"), NULL
, ngx_http_variable_is_args
,
223 0, NGX_HTTP_VAR_NOCACHEABLE
, 0 },
225 { ngx_string("request_filename"), NULL
,
226 ngx_http_variable_request_filename
, 0,
227 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
229 { ngx_string("server_name"), NULL
, ngx_http_variable_server_name
, 0, 0, 0 },
231 { ngx_string("request_method"), NULL
,
232 ngx_http_variable_request_method
, 0,
233 NGX_HTTP_VAR_NOCACHEABLE
, 0 },
235 { ngx_string("remote_user"), NULL
, ngx_http_variable_remote_user
, 0, 0, 0 },
237 { ngx_string("body_bytes_sent"), NULL
, ngx_http_variable_body_bytes_sent
,
240 { ngx_string("request_completion"), NULL
,
241 ngx_http_variable_request_completion
,
244 { ngx_string("request_body"), NULL
,
245 ngx_http_variable_request_body
,
248 { ngx_string("request_body_file"), NULL
,
249 ngx_http_variable_request_body_file
,
252 { ngx_string("sent_http_content_type"), NULL
,
253 ngx_http_variable_sent_content_type
, 0, 0, 0 },
255 { ngx_string("sent_http_content_length"), NULL
,
256 ngx_http_variable_sent_content_length
, 0, 0, 0 },
258 { ngx_string("sent_http_location"), NULL
,
259 ngx_http_variable_sent_location
, 0, 0, 0 },
261 { ngx_string("sent_http_last_modified"), NULL
,
262 ngx_http_variable_sent_last_modified
, 0, 0, 0 },
264 { ngx_string("sent_http_etag"), NULL
,
265 ngx_http_variable_sent_etag
, 0, 0, 0 },
267 { ngx_string("sent_http_connection"), NULL
,
268 ngx_http_variable_sent_connection
, 0, 0, 0 },
270 { ngx_string("sent_http_keep_alive"), NULL
,
271 ngx_http_variable_sent_keep_alive
, 0, 0, 0 },
273 { ngx_string("sent_http_transfer_encoding"), NULL
,
274 ngx_http_variable_sent_transfer_encoding
, 0, 0, 0 },
276 { ngx_string("sent_http_cache_control"), NULL
, ngx_http_variable_headers
,
277 offsetof(ngx_http_request_t
, headers_out
.cache_control
), 0, 0 },
279 { ngx_string("limit_rate"), ngx_http_variable_request_set_size
,
280 ngx_http_variable_request_get_size
,
281 offsetof(ngx_http_request_t
, limit_rate
),
282 NGX_HTTP_VAR_CHANGEABLE
|NGX_HTTP_VAR_NOCACHEABLE
, 0 },
284 { ngx_string("nginx_version"), NULL
, ngx_http_variable_nginx_version
,
287 { ngx_string("hostname"), NULL
, ngx_http_variable_hostname
,
290 { ngx_string("pid"), NULL
, ngx_http_variable_pid
,
293 { ngx_string("timestamp"), NULL
, ngx_http_variable_timestamp
,
296 { ngx_string("mstimestamp"), NULL
, ngx_http_variable_mstimestamp
,
299 { ngx_string("loadavg_1m"), NULL
, ngx_http_variable_loadavg_1m
,
302 { ngx_string("loadavg_5m"), NULL
, ngx_http_variable_loadavg_5m
,
305 { ngx_string("loadavg_15m"), NULL
, ngx_http_variable_loadavg_15m
,
308 { ngx_null_string
, NULL
, NULL
, 0, 0, 0 }
312 ngx_http_variable_value_t ngx_http_variable_null_value
=
313 ngx_http_variable("");
314 ngx_http_variable_value_t ngx_http_variable_true_value
=
315 ngx_http_variable("1");
318 ngx_http_variable_t
*
319 ngx_http_add_variable(ngx_conf_t
*cf
, ngx_str_t
*name
, ngx_uint_t flags
)
324 ngx_http_variable_t
*v
;
325 ngx_http_core_main_conf_t
*cmcf
;
327 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
329 key
= cmcf
->variables_keys
->keys
.elts
;
330 for (i
= 0; i
< cmcf
->variables_keys
->keys
.nelts
; i
++) {
331 if (name
->len
!= key
[i
].key
.len
332 || ngx_strncasecmp(name
->data
, key
[i
].key
.data
, name
->len
) != 0)
339 if (!(v
->flags
& NGX_HTTP_VAR_CHANGEABLE
)) {
340 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
341 "the duplicate \"%V\" variable", name
);
348 v
= ngx_palloc(cf
->pool
, sizeof(ngx_http_variable_t
));
353 v
->name
.len
= name
->len
;
354 v
->name
.data
= ngx_pnalloc(cf
->pool
, name
->len
);
355 if (v
->name
.data
== NULL
) {
359 ngx_strlow(v
->name
.data
, name
->data
, name
->len
);
361 v
->set_handler
= NULL
;
362 v
->get_handler
= NULL
;
367 rc
= ngx_hash_add_key(cmcf
->variables_keys
, &v
->name
, v
, 0);
369 if (rc
== NGX_ERROR
) {
373 if (rc
== NGX_BUSY
) {
374 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
375 "conflicting variable name \"%V\"", name
);
384 ngx_http_get_variable_index(ngx_conf_t
*cf
, ngx_str_t
*name
)
387 ngx_http_variable_t
*v
;
388 ngx_http_core_main_conf_t
*cmcf
;
390 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
392 v
= cmcf
->variables
.elts
;
395 if (ngx_array_init(&cmcf
->variables
, cf
->pool
, 4,
396 sizeof(ngx_http_variable_t
))
403 for (i
= 0; i
< cmcf
->variables
.nelts
; i
++) {
404 if (name
->len
!= v
[i
].name
.len
405 || ngx_strncasecmp(name
->data
, v
[i
].name
.data
, name
->len
) != 0)
414 v
= ngx_array_push(&cmcf
->variables
);
419 v
->name
.len
= name
->len
;
420 v
->name
.data
= ngx_pnalloc(cf
->pool
, name
->len
);
421 if (v
->name
.data
== NULL
) {
425 ngx_strlow(v
->name
.data
, name
->data
, name
->len
);
427 v
->set_handler
= NULL
;
428 v
->get_handler
= NULL
;
431 v
->index
= cmcf
->variables
.nelts
- 1;
433 return cmcf
->variables
.nelts
- 1;
437 ngx_http_variable_value_t
*
438 ngx_http_get_indexed_variable(ngx_http_request_t
*r
, ngx_uint_t index
)
440 ngx_http_variable_t
*v
;
441 ngx_http_core_main_conf_t
*cmcf
;
443 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
445 if (cmcf
->variables
.nelts
<= index
) {
446 ngx_log_error(NGX_LOG_ALERT
, r
->connection
->log
, 0,
447 "unknown variable index: %d", index
);
451 if (r
->variables
[index
].not_found
|| r
->variables
[index
].valid
) {
452 return &r
->variables
[index
];
455 v
= cmcf
->variables
.elts
;
457 if (v
[index
].get_handler(r
, &r
->variables
[index
], v
[index
].data
)
460 if (v
[index
].flags
& NGX_HTTP_VAR_NOCACHEABLE
) {
461 r
->variables
[index
].no_cacheable
= 1;
464 return &r
->variables
[index
];
467 r
->variables
[index
].valid
= 0;
468 r
->variables
[index
].not_found
= 1;
474 ngx_http_variable_value_t
*
475 ngx_http_get_flushed_variable(ngx_http_request_t
*r
, ngx_uint_t index
)
477 ngx_http_variable_value_t
*v
;
479 v
= &r
->variables
[index
];
482 if (!v
->no_cacheable
) {
490 return ngx_http_get_indexed_variable(r
, index
);
494 ngx_http_variable_value_t
*
495 ngx_http_get_variable(ngx_http_request_t
*r
, ngx_str_t
*name
, ngx_uint_t key
)
497 ngx_http_variable_t
*v
;
498 ngx_http_variable_value_t
*vv
;
499 ngx_http_core_main_conf_t
*cmcf
;
501 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
503 v
= ngx_hash_find(&cmcf
->variables_hash
, key
, name
->data
, name
->len
);
506 if (v
->flags
& NGX_HTTP_VAR_INDEXED
) {
507 return ngx_http_get_flushed_variable(r
, v
->index
);
511 vv
= ngx_palloc(r
->pool
, sizeof(ngx_http_variable_value_t
));
513 if (vv
&& v
->get_handler(r
, vv
, v
->data
) == NGX_OK
) {
521 vv
= ngx_palloc(r
->pool
, sizeof(ngx_http_variable_value_t
));
526 if (ngx_strncmp(name
->data
, "http_", 5) == 0) {
528 if (ngx_http_variable_unknown_header_in(r
, vv
, (uintptr_t) name
)
537 if (ngx_strncmp(name
->data
, "sent_http_", 10) == 0) {
539 if (ngx_http_variable_unknown_header_out(r
, vv
, (uintptr_t) name
)
548 if (ngx_strncmp(name
->data
, "upstream_http_", 14) == 0) {
550 if (ngx_http_upstream_header_variable(r
, vv
, (uintptr_t) name
)
559 if (ngx_strncmp(name
->data
, "cookie_", 7) == 0) {
561 if (ngx_http_variable_cookie(r
, vv
, (uintptr_t) name
) == NGX_OK
) {
569 if (ngx_strncmp(name
->data
, "ssi_", 4) == 0) {
571 if (ngx_http_variable_ssi(r
, vv
, (uintptr_t) name
) == NGX_OK
) {
579 if (ngx_strncmp(name
->data
, "urlencode_", 10) == 0) {
581 if (ngx_http_variable_urlencode(r
, vv
, (uintptr_t) name
) == NGX_OK
) {
588 if (ngx_strncmp(name
->data
, "urldecode_", 10) == 0) {
590 if (ngx_http_variable_urldecode(r
, vv
, (uintptr_t) name
) == NGX_OK
) {
597 if (ngx_strncmp(name
->data
, "crc32_", 6) == 0) {
599 if (ngx_http_variable_crc32(r
, vv
, (uintptr_t) name
) == NGX_OK
) {
607 if (ngx_strncmp(name
->data
, "md5_", 4) == 0) {
609 if (ngx_http_variable_md5(r
, vv
, (uintptr_t) name
) == NGX_OK
) {
617 if (ngx_strncmp(name
->data
, "arg_", 4) == 0) {
619 if (ngx_http_variable_argument(r
, vv
, (uintptr_t) name
) == NGX_OK
) {
635 ngx_http_variable_request(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
640 s
= (ngx_str_t
*) ((char *) r
+ data
);
658 ngx_http_variable_request_set(ngx_http_request_t
*r
,
659 ngx_http_variable_value_t
*v
, uintptr_t data
)
663 s
= (ngx_str_t
*) ((char *) r
+ data
);
671 ngx_http_variable_request_get_size(ngx_http_request_t
*r
,
672 ngx_http_variable_value_t
*v
, uintptr_t data
)
676 sp
= (size_t *) ((char *) r
+ data
);
678 v
->data
= ngx_pnalloc(r
->pool
, NGX_SIZE_T_LEN
);
679 if (v
->data
== NULL
) {
683 v
->len
= ngx_sprintf(v
->data
, "%uz", *sp
) - v
->data
;
693 ngx_http_variable_request_set_size(ngx_http_request_t
*r
,
694 ngx_http_variable_value_t
*v
, uintptr_t data
)
702 s
= ngx_parse_size(&val
);
704 if (s
== NGX_ERROR
) {
705 ngx_log_error(NGX_LOG_ERR
, r
->connection
->log
, 0,
706 "invalid size \"%V\"", &val
);
710 sp
= (ssize_t
*) ((char *) r
+ data
);
719 ngx_http_variable_header(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
724 h
= *(ngx_table_elt_t
**) ((char *) r
+ data
);
727 v
->len
= h
->value
.len
;
731 v
->data
= h
->value
.data
;
742 ngx_http_variable_headers(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
751 a
= (ngx_array_t
*) ((char *) r
+ data
);
767 v
->len
= (*h
)->value
.len
;
768 v
->data
= (*h
)->value
.data
;
773 len
= - (ssize_t
) (sizeof("; ") - 1);
775 for (i
= 0; i
< n
; i
++) {
776 len
+= h
[i
]->value
.len
+ sizeof("; ") - 1;
779 p
= ngx_pnalloc(r
->pool
, len
);
787 for (i
= 0; /* void */ ; i
++) {
788 p
= ngx_copy(p
, h
[i
]->value
.data
, h
[i
]->value
.len
);
794 *p
++ = ';'; *p
++ = ' ';
802 ngx_http_variable_unknown_header_in(ngx_http_request_t
*r
,
803 ngx_http_variable_value_t
*v
, uintptr_t data
)
805 return ngx_http_variable_unknown_header(v
, (ngx_str_t
*) data
,
806 &r
->headers_in
.headers
.part
,
807 sizeof("http_") - 1);
812 ngx_http_variable_unknown_header_out(ngx_http_request_t
*r
,
813 ngx_http_variable_value_t
*v
, uintptr_t data
)
815 return ngx_http_variable_unknown_header(v
, (ngx_str_t
*) data
,
816 &r
->headers_out
.headers
.part
,
817 sizeof("sent_http_") - 1);
822 ngx_http_variable_unknown_header(ngx_http_variable_value_t
*v
, ngx_str_t
*var
,
823 ngx_list_part_t
*part
, size_t prefix
)
827 ngx_table_elt_t
*header
;
831 for (i
= 0; /* void */ ; i
++) {
833 if (i
>= part
->nelts
) {
834 if (part
->next
== NULL
) {
843 for (n
= 0; n
+ prefix
< var
->len
&& n
< header
[i
].key
.len
; n
++) {
844 ch
= header
[i
].key
.data
[n
];
846 if (ch
>= 'A' && ch
<= 'Z') {
849 } else if (ch
== '-') {
853 if (var
->data
[n
+ prefix
] != ch
) {
858 if (n
+ prefix
== var
->len
&& n
== header
[i
].key
.len
) {
859 v
->len
= header
[i
].value
.len
;
863 v
->data
= header
[i
].value
.data
;
876 ngx_http_variable_request_line(ngx_http_request_t
*r
,
877 ngx_http_variable_value_t
*v
, uintptr_t data
)
881 s
= r
->request_line
.data
;
884 s
= r
->request_start
;
891 for (p
= s
; p
< r
->header_in
->last
; p
++) {
892 if (*p
== CR
|| *p
== LF
) {
897 r
->request_line
.len
= p
- s
;
898 r
->request_line
.data
= s
;
901 v
->len
= r
->request_line
.len
;
912 ngx_http_variable_cookie(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
915 ngx_str_t
*name
= (ngx_str_t
*) data
;
919 s
.len
= name
->len
- (sizeof("cookie_") - 1);
920 s
.data
= name
->data
+ sizeof("cookie_") - 1;
922 if (ngx_http_parse_multi_header_lines(&r
->headers_in
.cookies
, &s
, &cookie
)
933 v
->data
= cookie
.data
;
941 ngx_http_variable_ssi(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
944 ngx_str_t
*name
= (ngx_str_t
*) data
;
949 s
.len
= name
->len
- (sizeof("ssi_") - 1);
950 s
.data
= name
->data
+ sizeof("ssi_") - 1;
952 vv
= ngx_http_ssi_get_variable(r
, &s
, &key
);
971 ngx_http_variable_urlencode(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
974 ngx_str_t
*name
= (ngx_str_t
*) data
;
980 ngx_http_variable_value_t
*vv
;
982 sub_name
.len
= name
->len
- (sizeof("urlencode_") - 1);
983 sub_name
.data
= name
->data
+ sizeof("urlencode_") - 1;
985 key
= ngx_hash_strlow(sub_name
.data
, sub_name
.data
, sub_name
.len
);
987 vv
= ngx_http_get_variable(r
, &sub_name
, key
);
989 if (vv
== NULL
|| !vv
->valid
) {
999 2 * ngx_escape_uri(NULL
, vv
->data
, vv
->len
, NGX_ESCAPE_ARGS
);
1001 v
->data
= ngx_palloc(r
->pool
, v
->len
);
1002 if (v
->data
== NULL
) {
1007 (void) ngx_escape_uri(v
->data
, vv
->data
, vv
->len
, NGX_ESCAPE_ARGS
);
1011 v
->no_cacheable
= vv
->no_cacheable
;
1018 ngx_http_variable_urldecode(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
1021 ngx_str_t
*name
= (ngx_str_t
*) data
;
1027 ngx_http_variable_value_t
*vv
;
1029 sub_name
.len
= name
->len
- (sizeof("urldecode_") - 1);
1030 sub_name
.data
= name
->data
+ sizeof("urldecode_") - 1;
1032 key
= ngx_hash_strlow(sub_name
.data
, sub_name
.data
, sub_name
.len
);
1034 vv
= ngx_http_get_variable(r
, &sub_name
, key
);
1036 if (vv
== NULL
|| !vv
->valid
) {
1040 if (vv
->not_found
) {
1047 v
->data
= ngx_palloc(r
->pool
, v
->len
);
1048 if (v
->data
== NULL
) {
1056 ngx_unescape_uri(&dst
, &src
, vv
->len
, NGX_ESCAPE_ARGS
);
1058 v
->len
= dst
- v
->data
;
1062 v
->no_cacheable
= vv
->no_cacheable
;
1069 ngx_http_variable_crc32(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
1072 ngx_str_t
*name
= (ngx_str_t
*) data
;
1077 ngx_http_variable_value_t
*vv
;
1079 sub_name
.len
= name
->len
- (sizeof("crc32_") - 1);
1080 sub_name
.data
= name
->data
+ sizeof("crc32_") - 1;
1082 key
= ngx_hash_strlow(sub_name
.data
, sub_name
.data
, sub_name
.len
);
1084 vv
= ngx_http_get_variable(r
, &sub_name
, key
);
1086 if (vv
== NULL
|| !vv
->valid
) {
1090 if (vv
->not_found
) {
1095 v
->len
= sizeof("3C32515A") - 1;
1097 v
->data
= ngx_palloc(r
->pool
, v
->len
);
1098 if (v
->data
== NULL
) {
1103 ngx_sprintf(v
->data
, "%08XD", ngx_crc32_long(vv
->data
, vv
->len
));
1107 v
->no_cacheable
= vv
->no_cacheable
;
1115 ngx_http_variable_md5(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
1118 ngx_str_t
*name
= (ngx_str_t
*) data
;
1123 u_char hash
[16], *p
;
1125 ngx_http_variable_value_t
*vv
;
1127 sub_name
.len
= name
->len
- (sizeof("md5_") - 1);
1128 sub_name
.data
= name
->data
+ sizeof("md5_") - 1;
1130 key
= ngx_hash_strlow(sub_name
.data
, sub_name
.data
, sub_name
.len
);
1132 vv
= ngx_http_get_variable(r
, &sub_name
, key
);
1134 if (vv
== NULL
|| !vv
->valid
) {
1138 if (vv
->not_found
) {
1143 v
->len
= sizeof("7002945D4B8D9E472866092689DB3EAD") - 1;
1145 v
->data
= ngx_palloc(r
->pool
, v
->len
);
1146 if (v
->data
== NULL
) {
1152 ngx_md5_update(&md5
, vv
->data
, vv
->len
);
1153 ngx_md5_final((u_char
*)hash
, &md5
);
1157 for (i
= 0; i
< 16; i
++) {
1158 p
= ngx_sprintf(p
, "%02XD", hash
[i
]);
1163 v
->no_cacheable
= vv
->no_cacheable
;
1171 ngx_http_variable_argument(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
1174 ngx_str_t
*name
= (ngx_str_t
*) data
;
1180 len
= name
->len
- (sizeof("arg_") - 1);
1181 arg
= name
->data
+ sizeof("arg_") - 1;
1183 if (ngx_http_arg(r
, arg
, len
, &value
) != NGX_OK
) {
1188 v
->data
= value
.data
;
1191 v
->no_cacheable
= 0;
1199 ngx_http_variable_host(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
1202 ngx_http_core_srv_conf_t
*cscf
;
1204 if (r
->headers_in
.server
.len
) {
1205 v
->len
= r
->headers_in
.server
.len
;
1206 v
->data
= r
->headers_in
.server
.data
;
1209 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
1211 v
->len
= cscf
->server_name
.len
;
1212 v
->data
= cscf
->server_name
.data
;
1216 v
->no_cacheable
= 0;
1224 ngx_http_variable_binary_remote_addr(ngx_http_request_t
*r
,
1225 ngx_http_variable_value_t
*v
, uintptr_t data
)
1227 struct sockaddr_in
*sin
;
1228 #if (NGX_HAVE_INET6)
1229 struct sockaddr_in6
*sin6
;
1232 switch (r
->connection
->sockaddr
->sa_family
) {
1234 #if (NGX_HAVE_INET6)
1236 sin6
= (struct sockaddr_in6
*) r
->connection
->sockaddr
;
1238 v
->len
= sizeof(struct in6_addr
);
1240 v
->no_cacheable
= 0;
1242 v
->data
= sin6
->sin6_addr
.s6_addr
;
1247 default: /* AF_INET */
1248 sin
= (struct sockaddr_in
*) r
->connection
->sockaddr
;
1250 v
->len
= sizeof(in_addr_t
);
1252 v
->no_cacheable
= 0;
1254 v
->data
= (u_char
*) &sin
->sin_addr
;
1264 ngx_http_variable_remote_addr(ngx_http_request_t
*r
,
1265 ngx_http_variable_value_t
*v
, uintptr_t data
)
1267 v
->len
= r
->connection
->addr_text
.len
;
1269 v
->no_cacheable
= 0;
1271 v
->data
= r
->connection
->addr_text
.data
;
1278 ngx_http_variable_remote_port(ngx_http_request_t
*r
,
1279 ngx_http_variable_value_t
*v
, uintptr_t data
)
1282 struct sockaddr_in
*sin
;
1283 #if (NGX_HAVE_INET6)
1284 struct sockaddr_in6
*sin6
;
1289 v
->no_cacheable
= 0;
1292 v
->data
= ngx_pnalloc(r
->pool
, sizeof("65535") - 1);
1293 if (v
->data
== NULL
) {
1297 switch (r
->connection
->sockaddr
->sa_family
) {
1299 #if (NGX_HAVE_INET6)
1301 sin6
= (struct sockaddr_in6
*) r
->connection
->sockaddr
;
1302 port
= ntohs(sin6
->sin6_port
);
1306 default: /* AF_INET */
1307 sin
= (struct sockaddr_in
*) r
->connection
->sockaddr
;
1308 port
= ntohs(sin
->sin_port
);
1312 if (port
> 0 && port
< 65536) {
1313 v
->len
= ngx_sprintf(v
->data
, "%ui", port
) - v
->data
;
1321 ngx_http_variable_server_addr(ngx_http_request_t
*r
,
1322 ngx_http_variable_value_t
*v
, uintptr_t data
)
1325 u_char addr
[NGX_SOCKADDR_STRLEN
];
1327 s
.len
= NGX_SOCKADDR_STRLEN
;
1330 if (ngx_connection_local_sockaddr(r
->connection
, &s
, 0) != NGX_OK
) {
1334 s
.data
= ngx_pnalloc(r
->pool
, s
.len
);
1335 if (s
.data
== NULL
) {
1339 ngx_memcpy(s
.data
, addr
, s
.len
);
1343 v
->no_cacheable
= 0;
1352 ngx_http_variable_server_port(ngx_http_request_t
*r
,
1353 ngx_http_variable_value_t
*v
, uintptr_t data
)
1356 struct sockaddr_in
*sin
;
1357 #if (NGX_HAVE_INET6)
1358 struct sockaddr_in6
*sin6
;
1363 v
->no_cacheable
= 0;
1366 if (ngx_connection_local_sockaddr(r
->connection
, NULL
, 0) != NGX_OK
) {
1370 v
->data
= ngx_pnalloc(r
->pool
, sizeof("65535") - 1);
1371 if (v
->data
== NULL
) {
1375 switch (r
->connection
->local_sockaddr
->sa_family
) {
1377 #if (NGX_HAVE_INET6)
1379 sin6
= (struct sockaddr_in6
*) r
->connection
->local_sockaddr
;
1380 port
= ntohs(sin6
->sin6_port
);
1384 default: /* AF_INET */
1385 sin
= (struct sockaddr_in
*) r
->connection
->local_sockaddr
;
1386 port
= ntohs(sin
->sin_port
);
1390 if (port
> 0 && port
< 65536) {
1391 v
->len
= ngx_sprintf(v
->data
, "%ui", port
) - v
->data
;
1399 ngx_http_variable_scheme(ngx_http_request_t
*r
,
1400 ngx_http_variable_value_t
*v
, uintptr_t data
)
1404 if (r
->connection
->ssl
) {
1405 v
->len
= sizeof("https") - 1;
1407 v
->no_cacheable
= 0;
1409 v
->data
= (u_char
*) "https";
1416 v
->len
= sizeof("http") - 1;
1418 v
->no_cacheable
= 0;
1420 v
->data
= (u_char
*) "http";
1427 ngx_http_variable_is_args(ngx_http_request_t
*r
,
1428 ngx_http_variable_value_t
*v
, uintptr_t data
)
1431 v
->no_cacheable
= 0;
1434 if (r
->args
.len
== 0) {
1441 v
->data
= (u_char
*) "?";
1448 ngx_http_variable_document_root(ngx_http_request_t
*r
,
1449 ngx_http_variable_value_t
*v
, uintptr_t data
)
1452 ngx_http_core_loc_conf_t
*clcf
;
1454 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1456 if (clcf
->root_lengths
== NULL
) {
1457 v
->len
= clcf
->root
.len
;
1459 v
->no_cacheable
= 0;
1461 v
->data
= clcf
->root
.data
;
1464 if (ngx_http_script_run(r
, &path
, clcf
->root_lengths
->elts
, 0,
1465 clcf
->root_values
->elts
)
1471 if (ngx_conf_full_name((ngx_cycle_t
*) ngx_cycle
, &path
, 0) != NGX_OK
) {
1477 v
->no_cacheable
= 0;
1479 v
->data
= path
.data
;
1487 ngx_http_variable_realpath_root(ngx_http_request_t
*r
,
1488 ngx_http_variable_value_t
*v
, uintptr_t data
)
1492 ngx_http_core_loc_conf_t
*clcf
;
1493 u_char real
[NGX_MAX_PATH
];
1495 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1497 if (clcf
->root_lengths
== NULL
) {
1501 if (ngx_http_script_run(r
, &path
, clcf
->root_lengths
->elts
, 1,
1502 clcf
->root_values
->elts
)
1508 path
.data
[path
.len
- 1] = '\0';
1510 if (ngx_conf_full_name((ngx_cycle_t
*) ngx_cycle
, &path
, 0) != NGX_OK
) {
1515 if (ngx_realpath(path
.data
, real
) == NULL
) {
1516 ngx_log_error(NGX_LOG_CRIT
, r
->connection
->log
, ngx_errno
,
1517 ngx_realpath_n
" \"%s\" failed", path
.data
);
1521 len
= ngx_strlen(real
);
1523 v
->data
= ngx_pnalloc(r
->pool
, len
);
1524 if (v
->data
== NULL
) {
1530 v
->no_cacheable
= 0;
1533 ngx_memcpy(v
->data
, real
, len
);
1540 ngx_http_variable_request_filename(ngx_http_request_t
*r
,
1541 ngx_http_variable_value_t
*v
, uintptr_t data
)
1546 if (ngx_http_map_uri_to_path(r
, &path
, &root
, 0) == NULL
) {
1550 /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */
1552 v
->len
= path
.len
- 1;
1554 v
->no_cacheable
= 0;
1556 v
->data
= path
.data
;
1563 ngx_http_variable_server_name(ngx_http_request_t
*r
,
1564 ngx_http_variable_value_t
*v
, uintptr_t data
)
1566 ngx_http_core_srv_conf_t
*cscf
;
1568 cscf
= ngx_http_get_module_srv_conf(r
, ngx_http_core_module
);
1570 v
->len
= cscf
->server_name
.len
;
1572 v
->no_cacheable
= 0;
1574 v
->data
= cscf
->server_name
.data
;
1581 ngx_http_variable_request_method(ngx_http_request_t
*r
,
1582 ngx_http_variable_value_t
*v
, uintptr_t data
)
1584 if (r
->main
->method_name
.data
) {
1585 v
->len
= r
->main
->method_name
.len
;
1587 v
->no_cacheable
= 0;
1589 v
->data
= r
->main
->method_name
.data
;
1600 ngx_http_variable_remote_user(ngx_http_request_t
*r
,
1601 ngx_http_variable_value_t
*v
, uintptr_t data
)
1605 rc
= ngx_http_auth_basic_user(r
);
1607 if (rc
== NGX_DECLINED
) {
1612 if (rc
== NGX_ERROR
) {
1616 v
->len
= r
->headers_in
.user
.len
;
1618 v
->no_cacheable
= 0;
1620 v
->data
= r
->headers_in
.user
.data
;
1627 ngx_http_variable_body_bytes_sent(ngx_http_request_t
*r
,
1628 ngx_http_variable_value_t
*v
, uintptr_t data
)
1633 sent
= r
->connection
->sent
- r
->header_size
;
1639 p
= ngx_pnalloc(r
->pool
, NGX_OFF_T_LEN
);
1644 v
->len
= ngx_sprintf(p
, "%O", sent
) - p
;
1646 v
->no_cacheable
= 0;
1655 ngx_http_variable_sent_content_type(ngx_http_request_t
*r
,
1656 ngx_http_variable_value_t
*v
, uintptr_t data
)
1658 if (r
->headers_out
.content_type
.len
) {
1659 v
->len
= r
->headers_out
.content_type
.len
;
1661 v
->no_cacheable
= 0;
1663 v
->data
= r
->headers_out
.content_type
.data
;
1674 ngx_http_variable_sent_content_length(ngx_http_request_t
*r
,
1675 ngx_http_variable_value_t
*v
, uintptr_t data
)
1679 if (r
->headers_out
.content_length
) {
1680 v
->len
= r
->headers_out
.content_length
->value
.len
;
1682 v
->no_cacheable
= 0;
1684 v
->data
= r
->headers_out
.content_length
->value
.data
;
1689 if (r
->headers_out
.content_length_n
>= 0) {
1690 p
= ngx_pnalloc(r
->pool
, NGX_OFF_T_LEN
);
1695 v
->len
= ngx_sprintf(p
, "%O", r
->headers_out
.content_length_n
) - p
;
1697 v
->no_cacheable
= 0;
1711 ngx_http_variable_sent_location(ngx_http_request_t
*r
,
1712 ngx_http_variable_value_t
*v
, uintptr_t data
)
1716 if (r
->headers_out
.location
) {
1717 v
->len
= r
->headers_out
.location
->value
.len
;
1719 v
->no_cacheable
= 0;
1721 v
->data
= r
->headers_out
.location
->value
.data
;
1726 ngx_str_set(&name
, "sent_http_location");
1728 return ngx_http_variable_unknown_header(v
, &name
,
1729 &r
->headers_out
.headers
.part
,
1730 sizeof("sent_http_") - 1);
1735 ngx_http_variable_sent_last_modified(ngx_http_request_t
*r
,
1736 ngx_http_variable_value_t
*v
, uintptr_t data
)
1740 if (r
->headers_out
.last_modified
) {
1741 v
->len
= r
->headers_out
.last_modified
->value
.len
;
1743 v
->no_cacheable
= 0;
1745 v
->data
= r
->headers_out
.last_modified
->value
.data
;
1750 if (r
->headers_out
.last_modified_time
>= 0) {
1751 p
= ngx_pnalloc(r
->pool
,
1752 sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT") - 1);
1757 v
->len
= ngx_http_time(p
, r
->headers_out
.last_modified_time
) - p
;
1759 v
->no_cacheable
= 0;
1773 ngx_http_variable_sent_etag(ngx_http_request_t
*r
,
1774 ngx_http_variable_value_t
*v
, uintptr_t data
)
1778 if (r
->headers_out
.etag
) {
1779 v
->len
= r
->headers_out
.etag
->value
.len
;
1781 v
->no_cacheable
= 0;
1783 v
->data
= r
->headers_out
.etag
->value
.data
;
1788 if (r
->headers_out
.etag_size
>= 0 &&
1789 r
->headers_out
.etag_time
>= 0 &&
1790 (ngx_int_t
)r
->headers_out
.etag_uniq
>= 0) {
1791 p
= ngx_pnalloc(r
->pool
,
1792 sizeof("ETag: ") - 1 + NGX_OFF_T_LEN
+ sizeof("_") - 1
1793 + NGX_TIME_T_LEN
+ sizeof("_") - 1 + NGX_INT_T_LEN
);
1798 v
->len
= ngx_sprintf(p
, "ETag: %XO-%XM-%Xd",
1799 r
->headers_out
.etag_size
,
1800 r
->headers_out
.etag_time
,
1801 r
->headers_out
.etag_uniq
) - p
;
1803 v
->no_cacheable
= 0;
1817 ngx_http_variable_sent_connection(ngx_http_request_t
*r
,
1818 ngx_http_variable_value_t
*v
, uintptr_t data
)
1824 len
= sizeof("keep-alive") - 1;
1828 len
= sizeof("close") - 1;
1834 v
->no_cacheable
= 0;
1836 v
->data
= (u_char
*) p
;
1843 ngx_http_variable_sent_keep_alive(ngx_http_request_t
*r
,
1844 ngx_http_variable_value_t
*v
, uintptr_t data
)
1847 ngx_http_core_loc_conf_t
*clcf
;
1850 clcf
= ngx_http_get_module_loc_conf(r
, ngx_http_core_module
);
1852 if (clcf
->keepalive_header
) {
1854 p
= ngx_pnalloc(r
->pool
, sizeof("timeout=") - 1 + NGX_TIME_T_LEN
);
1859 v
->len
= ngx_sprintf(p
, "timeout=%T", clcf
->keepalive_header
) - p
;
1861 v
->no_cacheable
= 0;
1876 ngx_http_variable_sent_transfer_encoding(ngx_http_request_t
*r
,
1877 ngx_http_variable_value_t
*v
, uintptr_t data
)
1880 v
->len
= sizeof("chunked") - 1;
1882 v
->no_cacheable
= 0;
1884 v
->data
= (u_char
*) "chunked";
1895 ngx_http_variable_request_completion(ngx_http_request_t
*r
,
1896 ngx_http_variable_value_t
*v
, uintptr_t data
)
1898 if (r
->request_complete
) {
1901 v
->no_cacheable
= 0;
1903 v
->data
= (u_char
*) "OK";
1910 v
->no_cacheable
= 0;
1912 v
->data
= (u_char
*) "";
1919 ngx_http_variable_request_body(ngx_http_request_t
*r
,
1920 ngx_http_variable_value_t
*v
, uintptr_t data
)
1924 ngx_buf_t
*buf
, *next
;
1927 if (r
->request_body
== NULL
1928 || r
->request_body
->bufs
== NULL
1929 || r
->request_body
->temp_file
)
1936 cl
= r
->request_body
->bufs
;
1939 if (cl
->next
== NULL
) {
1940 v
->len
= buf
->last
- buf
->pos
;
1942 v
->no_cacheable
= 0;
1949 next
= cl
->next
->buf
;
1950 len
= (buf
->last
- buf
->pos
) + (next
->last
- next
->pos
);
1952 p
= ngx_pnalloc(r
->pool
, len
);
1959 p
= ngx_cpymem(p
, buf
->pos
, buf
->last
- buf
->pos
);
1960 ngx_memcpy(p
, next
->pos
, next
->last
- next
->pos
);
1964 v
->no_cacheable
= 0;
1972 ngx_http_variable_request_body_file(ngx_http_request_t
*r
,
1973 ngx_http_variable_value_t
*v
, uintptr_t data
)
1975 if (r
->request_body
== NULL
|| r
->request_body
->temp_file
== NULL
) {
1981 v
->len
= r
->request_body
->temp_file
->file
.name
.len
;
1983 v
->no_cacheable
= 0;
1985 v
->data
= r
->request_body
->temp_file
->file
.name
.data
;
1992 ngx_http_variable_nginx_version(ngx_http_request_t
*r
,
1993 ngx_http_variable_value_t
*v
, uintptr_t data
)
1995 v
->len
= sizeof(NGINX_VERSION
) - 1;
1997 v
->no_cacheable
= 0;
1999 v
->data
= (u_char
*) NGINX_VERSION
;
2006 ngx_http_variable_hostname(ngx_http_request_t
*r
,
2007 ngx_http_variable_value_t
*v
, uintptr_t data
)
2009 v
->len
= ngx_cycle
->hostname
.len
;
2011 v
->no_cacheable
= 0;
2013 v
->data
= ngx_cycle
->hostname
.data
;
2020 ngx_http_variable_pid(ngx_http_request_t
*r
,
2021 ngx_http_variable_value_t
*v
, uintptr_t data
)
2025 p
= ngx_pnalloc(r
->pool
, NGX_INT_T_LEN
);
2030 v
->len
= ngx_sprintf(p
, "%P", ngx_pid
) - p
;
2032 v
->no_cacheable
= 0;
2040 ngx_http_variable_timestamp(ngx_http_request_t
*r
,
2041 ngx_http_variable_value_t
*v
, uintptr_t data
)
2045 p
= ngx_pnalloc(r
->pool
, NGX_INT64_LEN
);
2050 v
->len
= ngx_sprintf(p
, "%T", ngx_time()) - p
;
2052 v
->no_cacheable
= 0;
2061 ngx_http_variable_mstimestamp(ngx_http_request_t
*r
,
2062 ngx_http_variable_value_t
*v
, uintptr_t data
)
2066 p
= ngx_pnalloc(r
->pool
, NGX_INT64_LEN
+ sizeof("123") - 1);
2071 v
->len
= ngx_sprintf(p
, "%T%03M", ngx_time(), (ngx_timeofday())->msec
) - p
;
2073 v
->no_cacheable
= 0;
2082 ngx_http_variable_loadavg_1m(ngx_http_request_t
*r
,
2083 ngx_http_variable_value_t
*v
, uintptr_t data
)
2088 p
= ngx_pnalloc(r
->pool
, NGX_INT64_LEN
);
2093 la
= ngx_get_loadavg(0);
2094 if (la
== NGX_ERROR
) {
2098 v
->len
= ngx_sprintf(p
, "%i", la
) - p
;
2100 v
->no_cacheable
= 1;
2109 ngx_http_variable_loadavg_5m(ngx_http_request_t
*r
,
2110 ngx_http_variable_value_t
*v
, uintptr_t data
)
2115 p
= ngx_pnalloc(r
->pool
, NGX_INT_T_LEN
);
2120 la
= ngx_get_loadavg(1);
2121 if (la
== NGX_ERROR
) {
2125 v
->len
= ngx_sprintf(p
, "%i", la
) - p
;
2127 v
->no_cacheable
= 1;
2136 ngx_http_variable_loadavg_15m(ngx_http_request_t
*r
,
2137 ngx_http_variable_value_t
*v
, uintptr_t data
)
2142 p
= ngx_pnalloc(r
->pool
, NGX_INT_T_LEN
);
2147 la
= ngx_get_loadavg(2);
2148 if (la
== NGX_ERROR
) {
2152 v
->len
= ngx_sprintf(p
, "%i", la
) - p
;
2154 v
->no_cacheable
= 1;
2165 ngx_http_variable_not_found(ngx_http_request_t
*r
, ngx_http_variable_value_t
*v
,
2174 ngx_http_regex_compile(ngx_conf_t
*cf
, ngx_regex_compile_t
*rc
)
2180 ngx_http_variable_t
*v
;
2181 ngx_http_regex_t
*re
;
2182 ngx_http_regex_variable_t
*rv
;
2183 ngx_http_core_main_conf_t
*cmcf
;
2185 rc
->pool
= cf
->pool
;
2187 if (ngx_regex_compile(rc
) != NGX_OK
) {
2188 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0, "%V", &rc
->err
);
2192 re
= ngx_pcalloc(cf
->pool
, sizeof(ngx_http_regex_t
));
2197 re
->regex
= rc
->regex
;
2198 re
->ncaptures
= rc
->captures
;
2200 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
2201 cmcf
->ncaptures
= ngx_max(cmcf
->ncaptures
, re
->ncaptures
);
2203 n
= (ngx_uint_t
) rc
->named_captures
;
2209 rv
= ngx_palloc(rc
->pool
, n
* sizeof(ngx_http_regex_variable_t
));
2216 re
->name
= rc
->pattern
;
2218 size
= rc
->name_size
;
2221 for (i
= 0; i
< n
; i
++) {
2222 rv
[i
].capture
= 2 * ((p
[0] << 8) + p
[1]);
2225 name
.len
= ngx_strlen(name
.data
);
2227 v
= ngx_http_add_variable(cf
, &name
, NGX_HTTP_VAR_CHANGEABLE
);
2232 rv
[i
].index
= ngx_http_get_variable_index(cf
, &name
);
2233 if (rv
[i
].index
== NGX_ERROR
) {
2237 v
->get_handler
= ngx_http_variable_not_found
;
2247 ngx_http_regex_exec(ngx_http_request_t
*r
, ngx_http_regex_t
*re
, ngx_str_t
*s
)
2249 ngx_int_t rc
, index
;
2250 ngx_uint_t i
, n
, len
;
2251 ngx_http_variable_value_t
*vv
;
2252 ngx_http_core_main_conf_t
*cmcf
;
2254 cmcf
= ngx_http_get_module_main_conf(r
, ngx_http_core_module
);
2256 if (re
->ncaptures
) {
2257 len
= cmcf
->ncaptures
;
2259 if (r
->captures
== NULL
) {
2260 r
->captures
= ngx_palloc(r
->pool
, len
* sizeof(int));
2261 if (r
->captures
== NULL
) {
2270 rc
= ngx_regex_exec(re
->regex
, s
, r
->captures
, len
);
2272 if (rc
== NGX_REGEX_NO_MATCHED
) {
2273 return NGX_DECLINED
;
2277 ngx_log_error(NGX_LOG_ALERT
, r
->connection
->log
, 0,
2278 ngx_regex_exec_n
" failed: %i on \"%V\" using \"%V\"",
2283 for (i
= 0; i
< re
->nvariables
; i
++) {
2285 n
= re
->variables
[i
].capture
;
2286 index
= re
->variables
[i
].index
;
2287 vv
= &r
->variables
[index
];
2289 vv
->len
= r
->captures
[n
+ 1] - r
->captures
[n
];
2291 vv
->no_cacheable
= 0;
2293 vv
->data
= &s
->data
[r
->captures
[n
]];
2297 ngx_http_variable_t
*v
;
2299 v
= cmcf
->variables
.elts
;
2301 ngx_log_debug3(NGX_LOG_DEBUG_HTTP
, r
->connection
->log
, 0,
2302 "http regex set $%V to \"%*s\"",
2303 &v
[index
].name
, vv
->len
, vv
->data
);
2308 r
->ncaptures
= rc
* 2;
2309 r
->captures_data
= s
->data
;
2318 ngx_http_variables_add_core_vars(ngx_conf_t
*cf
)
2321 ngx_http_variable_t
*v
;
2322 ngx_http_core_main_conf_t
*cmcf
;
2324 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
2326 cmcf
->variables_keys
= ngx_pcalloc(cf
->temp_pool
,
2327 sizeof(ngx_hash_keys_arrays_t
));
2328 if (cmcf
->variables_keys
== NULL
) {
2332 cmcf
->variables_keys
->pool
= cf
->pool
;
2333 cmcf
->variables_keys
->temp_pool
= cf
->pool
;
2335 if (ngx_hash_keys_array_init(cmcf
->variables_keys
, NGX_HASH_SMALL
)
2341 for (v
= ngx_http_core_variables
; v
->name
.len
; v
++) {
2342 rc
= ngx_hash_add_key(cmcf
->variables_keys
, &v
->name
, v
,
2343 NGX_HASH_READONLY_KEY
);
2349 if (rc
== NGX_BUSY
) {
2350 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
2351 "conflicting variable name \"%V\"", &v
->name
);
2362 ngx_http_variables_init_vars(ngx_conf_t
*cf
)
2365 ngx_hash_key_t
*key
;
2366 ngx_hash_init_t hash
;
2367 ngx_http_variable_t
*v
, *av
;
2368 ngx_http_core_main_conf_t
*cmcf
;
2370 /* set the handlers for the indexed http variables */
2372 cmcf
= ngx_http_conf_get_module_main_conf(cf
, ngx_http_core_module
);
2374 v
= cmcf
->variables
.elts
;
2375 key
= cmcf
->variables_keys
->keys
.elts
;
2377 for (i
= 0; i
< cmcf
->variables
.nelts
; i
++) {
2379 for (n
= 0; n
< cmcf
->variables_keys
->keys
.nelts
; n
++) {
2384 && v
[i
].name
.len
== key
[n
].key
.len
2385 && ngx_strncmp(v
[i
].name
.data
, key
[n
].key
.data
, v
[i
].name
.len
)
2388 v
[i
].get_handler
= av
->get_handler
;
2389 v
[i
].data
= av
->data
;
2391 av
->flags
|= NGX_HTTP_VAR_INDEXED
;
2392 v
[i
].flags
= av
->flags
;
2400 if (ngx_strncmp(v
[i
].name
.data
, "http_", 5) == 0) {
2401 v
[i
].get_handler
= ngx_http_variable_unknown_header_in
;
2402 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2407 if (ngx_strncmp(v
[i
].name
.data
, "sent_http_", 10) == 0) {
2408 v
[i
].get_handler
= ngx_http_variable_unknown_header_out
;
2409 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2414 if (ngx_strncmp(v
[i
].name
.data
, "upstream_http_", 14) == 0) {
2415 v
[i
].get_handler
= ngx_http_upstream_header_variable
;
2416 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2417 v
[i
].flags
= NGX_HTTP_VAR_NOCACHEABLE
;
2422 if (ngx_strncmp(v
[i
].name
.data
, "cookie_", 7) == 0) {
2423 v
[i
].get_handler
= ngx_http_variable_cookie
;
2424 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2430 if (ngx_strncmp(v
[i
].name
.data
, "ssi_", 7) == 0) {
2431 v
[i
].get_handler
= ngx_http_variable_ssi
;
2432 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2438 if (ngx_strncmp(v
[i
].name
.data
, "urlencode_", 10) == 0) {
2439 v
[i
].get_handler
= ngx_http_variable_urlencode
;
2440 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2445 if (ngx_strncmp(v
[i
].name
.data
, "urldecode_", 10) == 0) {
2446 v
[i
].get_handler
= ngx_http_variable_urldecode
;
2447 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2452 if (ngx_strncmp(v
[i
].name
.data
, "crc32_", 6) == 0) {
2453 v
[i
].get_handler
= ngx_http_variable_crc32
;
2454 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2460 if (ngx_strncmp(v
[i
].name
.data
, "md5_", 4) == 0) {
2461 v
[i
].get_handler
= ngx_http_variable_md5
;
2462 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2468 if (ngx_strncmp(v
[i
].name
.data
, "arg_", 4) == 0) {
2469 v
[i
].get_handler
= ngx_http_variable_argument
;
2470 v
[i
].data
= (uintptr_t) &v
[i
].name
;
2471 v
[i
].flags
= NGX_HTTP_VAR_NOCACHEABLE
;
2476 ngx_log_error(NGX_LOG_EMERG
, cf
->log
, 0,
2477 "unknown \"%V\" variable", &v
[i
].name
);
2486 for (n
= 0; n
< cmcf
->variables_keys
->keys
.nelts
; n
++) {
2489 if (av
->flags
& NGX_HTTP_VAR_NOHASH
) {
2490 key
[n
].key
.data
= NULL
;
2495 hash
.hash
= &cmcf
->variables_hash
;
2496 hash
.key
= ngx_hash_key
;
2497 hash
.max_size
= cmcf
->variables_hash_max_size
;
2498 hash
.bucket_size
= cmcf
->variables_hash_bucket_size
;
2499 hash
.name
= "variables_hash";
2500 hash
.pool
= cf
->pool
;
2501 hash
.temp_pool
= NULL
;
2503 if (ngx_hash_init(&hash
, cmcf
->variables_keys
->keys
.elts
,
2504 cmcf
->variables_keys
->keys
.nelts
)
2510 cmcf
->variables_keys
= NULL
;
2517 ngx_http_variable_value_rbtree_insert(ngx_rbtree_node_t
*temp
,
2518 ngx_rbtree_node_t
*node
, ngx_rbtree_node_t
*sentinel
)
2520 ngx_rbtree_node_t
**p
;
2521 ngx_http_variable_value_node_t
*vvn
, *vvt
;
2525 vvn
= (ngx_http_variable_value_node_t
*) node
;
2526 vvt
= (ngx_http_variable_value_node_t
*) temp
;
2528 if (node
->key
!= temp
->key
) {
2530 p
= (node
->key
< temp
->key
) ? &temp
->left
: &temp
->right
;
2532 } else if (vvn
->len
!= vvt
->len
) {
2534 p
= (vvn
->len
< vvt
->len
) ? &temp
->left
: &temp
->right
;
2537 p
= (ngx_memcmp(vvn
->value
->data
, vvt
->value
->data
, vvn
->len
) < 0)
2538 ? &temp
->left
: &temp
->right
;
2541 if (*p
== sentinel
) {
2549 node
->parent
= temp
;
2550 node
->left
= sentinel
;
2551 node
->right
= sentinel
;
2556 ngx_http_variable_value_t
*
2557 ngx_http_variable_value_lookup(ngx_rbtree_t
*rbtree
, ngx_str_t
*val
,
2561 ngx_rbtree_node_t
*node
, *sentinel
;
2562 ngx_http_variable_value_node_t
*vvn
;
2564 node
= rbtree
->root
;
2565 sentinel
= rbtree
->sentinel
;
2567 while (node
!= sentinel
) {
2569 vvn
= (ngx_http_variable_value_node_t
*) node
;
2571 if (hash
!= node
->key
) {
2572 node
= (hash
< node
->key
) ? node
->left
: node
->right
;
2576 if (val
->len
!= vvn
->len
) {
2577 node
= (val
->len
< vvn
->len
) ? node
->left
: node
->right
;
2581 rc
= ngx_memcmp(val
->data
, vvn
->value
->data
, val
->len
);