Fix work keepalive and rewrite to named location
[nginx-catap.git] / src / http / ngx_http_variables.c
blobbbb585d71544153572af6b2c648353d21cc216ba
2 /*
3 * Copyright (C) Igor Sysoev
4 */
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_http.h>
10 #if (NGX_HAVE_MD5)
11 #include <ngx_md5.h>
12 #endif
13 #include <nginx.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);
37 #if (NGX_HTTP_SSI)
38 static ngx_int_t ngx_http_variable_ssi(ngx_http_request_t *r,
39 ngx_http_variable_value_t *v, uintptr_t data);
40 #endif
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);
47 #if (NGX_HAVE_MD5)
48 static ngx_int_t ngx_http_variable_md5(ngx_http_request_t *r,
49 ngx_http_variable_value_t *v, uintptr_t data);
50 #endif
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);
126 * TODO:
127 * Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED
128 * REMOTE_HOST (null), REMOTE_IDENT (null),
129 * SERVER_SOFTWARE
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 },
152 #if (NGX_HTTP_GZIP)
153 { ngx_string("http_via"), NULL, ngx_http_variable_header,
154 offsetof(ngx_http_request_t, headers_in.via), 0, 0 },
155 #endif
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 },
160 #endif
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,
238 0, 0, 0 },
240 { ngx_string("request_completion"), NULL,
241 ngx_http_variable_request_completion,
242 0, 0, 0 },
244 { ngx_string("request_body"), NULL,
245 ngx_http_variable_request_body,
246 0, 0, 0 },
248 { ngx_string("request_body_file"), NULL,
249 ngx_http_variable_request_body_file,
250 0, 0, 0 },
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,
285 0, 0, 0 },
287 { ngx_string("hostname"), NULL, ngx_http_variable_hostname,
288 0, 0, 0 },
290 { ngx_string("pid"), NULL, ngx_http_variable_pid,
291 0, 0, 0 },
293 { ngx_string("timestamp"), NULL, ngx_http_variable_timestamp,
294 0, 0, 0 },
296 { ngx_string("mstimestamp"), NULL, ngx_http_variable_mstimestamp,
297 0, 0, 0 },
299 { ngx_string("loadavg_1m"), NULL, ngx_http_variable_loadavg_1m,
300 0, 0, 0 },
302 { ngx_string("loadavg_5m"), NULL, ngx_http_variable_loadavg_5m,
303 0, 0, 0 },
305 { ngx_string("loadavg_15m"), NULL, ngx_http_variable_loadavg_15m,
306 0, 0, 0 },
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)
321 ngx_int_t rc;
322 ngx_uint_t i;
323 ngx_hash_key_t *key;
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)
334 continue;
337 v = key[i].value;
339 if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
340 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
341 "the duplicate \"%V\" variable", name);
342 return NULL;
345 return v;
348 v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));
349 if (v == NULL) {
350 return NULL;
353 v->name.len = name->len;
354 v->name.data = ngx_pnalloc(cf->pool, name->len);
355 if (v->name.data == NULL) {
356 return NULL;
359 ngx_strlow(v->name.data, name->data, name->len);
361 v->set_handler = NULL;
362 v->get_handler = NULL;
363 v->data = 0;
364 v->flags = flags;
365 v->index = 0;
367 rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0);
369 if (rc == NGX_ERROR) {
370 return NULL;
373 if (rc == NGX_BUSY) {
374 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
375 "conflicting variable name \"%V\"", name);
376 return NULL;
379 return v;
383 ngx_int_t
384 ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name)
386 ngx_uint_t i;
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;
394 if (v == NULL) {
395 if (ngx_array_init(&cmcf->variables, cf->pool, 4,
396 sizeof(ngx_http_variable_t))
397 != NGX_OK)
399 return NGX_ERROR;
402 } else {
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)
407 continue;
410 return i;
414 v = ngx_array_push(&cmcf->variables);
415 if (v == NULL) {
416 return NGX_ERROR;
419 v->name.len = name->len;
420 v->name.data = ngx_pnalloc(cf->pool, name->len);
421 if (v->name.data == NULL) {
422 return NGX_ERROR;
425 ngx_strlow(v->name.data, name->data, name->len);
427 v->set_handler = NULL;
428 v->get_handler = NULL;
429 v->data = 0;
430 v->flags = 0;
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);
448 return NULL;
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)
458 == NGX_OK)
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;
470 return NULL;
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];
481 if (v->valid) {
482 if (!v->no_cacheable) {
483 return v;
486 v->valid = 0;
487 v->not_found = 0;
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);
505 if (v) {
506 if (v->flags & NGX_HTTP_VAR_INDEXED) {
507 return ngx_http_get_flushed_variable(r, v->index);
509 } else {
511 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
513 if (vv && v->get_handler(r, vv, v->data) == NGX_OK) {
514 return vv;
517 return NULL;
521 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
522 if (vv == NULL) {
523 return NULL;
526 if (ngx_strncmp(name->data, "http_", 5) == 0) {
528 if (ngx_http_variable_unknown_header_in(r, vv, (uintptr_t) name)
529 == NGX_OK)
531 return vv;
534 return NULL;
537 if (ngx_strncmp(name->data, "sent_http_", 10) == 0) {
539 if (ngx_http_variable_unknown_header_out(r, vv, (uintptr_t) name)
540 == NGX_OK)
542 return vv;
545 return NULL;
548 if (ngx_strncmp(name->data, "upstream_http_", 14) == 0) {
550 if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name)
551 == NGX_OK)
553 return vv;
556 return NULL;
559 if (ngx_strncmp(name->data, "cookie_", 7) == 0) {
561 if (ngx_http_variable_cookie(r, vv, (uintptr_t) name) == NGX_OK) {
562 return vv;
565 return NULL;
568 #if (NGX_HTTP_SSI)
569 if (ngx_strncmp(name->data, "ssi_", 4) == 0) {
571 if (ngx_http_variable_ssi(r, vv, (uintptr_t) name) == NGX_OK) {
572 return vv;
575 return NULL;
577 #endif
579 if (ngx_strncmp(name->data, "urlencode_", 10) == 0) {
581 if (ngx_http_variable_urlencode(r, vv, (uintptr_t) name) == NGX_OK) {
582 return vv;
585 return NULL;
588 if (ngx_strncmp(name->data, "urldecode_", 10) == 0) {
590 if (ngx_http_variable_urldecode(r, vv, (uintptr_t) name) == NGX_OK) {
591 return vv;
594 return NULL;
597 if (ngx_strncmp(name->data, "crc32_", 6) == 0) {
599 if (ngx_http_variable_crc32(r, vv, (uintptr_t) name) == NGX_OK) {
600 return vv;
603 return NULL;
606 #if (NGX_HAVE_MD5)
607 if (ngx_strncmp(name->data, "md5_", 4) == 0) {
609 if (ngx_http_variable_md5(r, vv, (uintptr_t) name) == NGX_OK) {
610 return vv;
613 return NULL;
615 #endif
617 if (ngx_strncmp(name->data, "arg_", 4) == 0) {
619 if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) {
620 return vv;
623 return NULL;
628 vv->not_found = 1;
630 return vv;
634 static ngx_int_t
635 ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v,
636 uintptr_t data)
638 ngx_str_t *s;
640 s = (ngx_str_t *) ((char *) r + data);
642 if (s->data) {
643 v->len = s->len;
644 v->valid = 1;
645 v->no_cacheable = 0;
646 v->not_found = 0;
647 v->data = s->data;
649 } else {
650 v->not_found = 1;
653 return NGX_OK;
657 static void
658 ngx_http_variable_request_set(ngx_http_request_t *r,
659 ngx_http_variable_value_t *v, uintptr_t data)
661 ngx_str_t *s;
663 s = (ngx_str_t *) ((char *) r + data);
665 s->len = v->len;
666 s->data = v->data;
670 static ngx_int_t
671 ngx_http_variable_request_get_size(ngx_http_request_t *r,
672 ngx_http_variable_value_t *v, uintptr_t data)
674 size_t *sp;
676 sp = (size_t *) ((char *) r + data);
678 v->data = ngx_pnalloc(r->pool, NGX_SIZE_T_LEN);
679 if (v->data == NULL) {
680 return NGX_ERROR;
683 v->len = ngx_sprintf(v->data, "%uz", *sp) - v->data;
684 v->valid = 1;
685 v->no_cacheable = 0;
686 v->not_found = 0;
688 return NGX_OK;
692 static void
693 ngx_http_variable_request_set_size(ngx_http_request_t *r,
694 ngx_http_variable_value_t *v, uintptr_t data)
696 ssize_t s, *sp;
697 ngx_str_t val;
699 val.len = v->len;
700 val.data = v->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);
707 return;
710 sp = (ssize_t *) ((char *) r + data);
712 *sp = s;
714 return;
718 static ngx_int_t
719 ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v,
720 uintptr_t data)
722 ngx_table_elt_t *h;
724 h = *(ngx_table_elt_t **) ((char *) r + data);
726 if (h) {
727 v->len = h->value.len;
728 v->valid = 1;
729 v->no_cacheable = 0;
730 v->not_found = 0;
731 v->data = h->value.data;
733 } else {
734 v->not_found = 1;
737 return NGX_OK;
741 static ngx_int_t
742 ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v,
743 uintptr_t data)
745 ssize_t len;
746 u_char *p;
747 ngx_uint_t i, n;
748 ngx_array_t *a;
749 ngx_table_elt_t **h;
751 a = (ngx_array_t *) ((char *) r + data);
753 n = a->nelts;
755 if (n == 0) {
756 v->not_found = 1;
757 return NGX_OK;
760 v->valid = 1;
761 v->no_cacheable = 0;
762 v->not_found = 0;
764 h = a->elts;
766 if (n == 1) {
767 v->len = (*h)->value.len;
768 v->data = (*h)->value.data;
770 return NGX_OK;
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);
780 if (p == NULL) {
781 return NGX_ERROR;
784 v->len = len;
785 v->data = p;
787 for (i = 0; /* void */ ; i++) {
788 p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
790 if (i == n - 1) {
791 break;
794 *p++ = ';'; *p++ = ' ';
797 return NGX_OK;
801 static ngx_int_t
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);
811 static ngx_int_t
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);
821 ngx_int_t
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)
825 u_char ch;
826 ngx_uint_t i, n;
827 ngx_table_elt_t *header;
829 header = part->elts;
831 for (i = 0; /* void */ ; i++) {
833 if (i >= part->nelts) {
834 if (part->next == NULL) {
835 break;
838 part = part->next;
839 header = part->elts;
840 i = 0;
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') {
847 ch |= 0x20;
849 } else if (ch == '-') {
850 ch = '_';
853 if (var->data[n + prefix] != ch) {
854 break;
858 if (n + prefix == var->len && n == header[i].key.len) {
859 v->len = header[i].value.len;
860 v->valid = 1;
861 v->no_cacheable = 0;
862 v->not_found = 0;
863 v->data = header[i].value.data;
865 return NGX_OK;
869 v->not_found = 1;
871 return NGX_OK;
875 static ngx_int_t
876 ngx_http_variable_request_line(ngx_http_request_t *r,
877 ngx_http_variable_value_t *v, uintptr_t data)
879 u_char *p, *s;
881 s = r->request_line.data;
883 if (s == NULL) {
884 s = r->request_start;
886 if (s == NULL) {
887 v->not_found = 1;
888 return NGX_OK;
891 for (p = s; p < r->header_in->last; p++) {
892 if (*p == CR || *p == LF) {
893 break;
897 r->request_line.len = p - s;
898 r->request_line.data = s;
901 v->len = r->request_line.len;
902 v->valid = 1;
903 v->no_cacheable = 0;
904 v->not_found = 0;
905 v->data = s;
907 return NGX_OK;
911 static ngx_int_t
912 ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v,
913 uintptr_t data)
915 ngx_str_t *name = (ngx_str_t *) data;
917 ngx_str_t cookie, s;
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)
923 == NGX_DECLINED)
925 v->not_found = 1;
926 return NGX_OK;
929 v->len = cookie.len;
930 v->valid = 1;
931 v->no_cacheable = 0;
932 v->not_found = 0;
933 v->data = cookie.data;
935 return NGX_OK;
939 #if (NGX_HTTP_SSI)
940 static ngx_int_t
941 ngx_http_variable_ssi(ngx_http_request_t *r, ngx_http_variable_value_t *v,
942 uintptr_t data)
944 ngx_str_t *name = (ngx_str_t *) data;
945 ngx_str_t *vv;
946 ngx_str_t s;
947 ngx_uint_t key;
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);
954 if (vv == NULL) {
955 v->not_found = 1;
956 return NGX_OK;
959 v->len = vv->len;
960 v->valid = 1;
961 v->no_cacheable = 1;
962 v->not_found = 0;
963 v->data = vv->data;
965 return NGX_OK;
967 #endif
970 static ngx_int_t
971 ngx_http_variable_urlencode(ngx_http_request_t *r, ngx_http_variable_value_t *v,
972 uintptr_t data)
974 ngx_str_t *name = (ngx_str_t *) data;
976 ngx_str_t sub_name;
978 ngx_uint_t key;
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) {
990 return NGX_ERROR;
993 if (vv->not_found) {
994 v->not_found = 1;
995 return NGX_OK;
998 v->len = vv->len +
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) {
1003 v->not_found = 1;
1004 return NGX_OK;
1007 (void) ngx_escape_uri(v->data, vv->data, vv->len, NGX_ESCAPE_ARGS);
1009 v->valid = 1;
1010 v->not_found = 0;
1011 v->no_cacheable = vv->no_cacheable;
1013 return NGX_OK;
1017 static ngx_int_t
1018 ngx_http_variable_urldecode(ngx_http_request_t *r, ngx_http_variable_value_t *v,
1019 uintptr_t data)
1021 ngx_str_t *name = (ngx_str_t *) data;
1023 u_char *dst, *src;
1024 ngx_str_t sub_name;
1025 ngx_uint_t key;
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) {
1037 return NGX_ERROR;
1040 if (vv->not_found) {
1041 v->not_found = 1;
1042 return NGX_OK;
1045 v->len = vv->len;
1047 v->data = ngx_palloc(r->pool, v->len);
1048 if (v->data == NULL) {
1049 v->not_found = 1;
1050 return NGX_OK;
1053 dst = v->data;
1054 src = vv->data;
1056 ngx_unescape_uri(&dst, &src, vv->len, NGX_ESCAPE_ARGS);
1058 v->len = dst - v->data;
1060 v->valid = 1;
1061 v->not_found = 0;
1062 v->no_cacheable = vv->no_cacheable;
1064 return NGX_OK;
1068 static ngx_int_t
1069 ngx_http_variable_crc32(ngx_http_request_t *r, ngx_http_variable_value_t *v,
1070 uintptr_t data)
1072 ngx_str_t *name = (ngx_str_t *) data;
1074 ngx_str_t sub_name;
1075 ngx_uint_t key;
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) {
1087 return NGX_ERROR;
1090 if (vv->not_found) {
1091 v->not_found = 1;
1092 return NGX_OK;
1095 v->len = sizeof("3C32515A") - 1;
1097 v->data = ngx_palloc(r->pool, v->len);
1098 if (v->data == NULL) {
1099 v->not_found = 1;
1100 return NGX_OK;
1103 ngx_sprintf(v->data, "%08XD", ngx_crc32_long(vv->data, vv->len));
1105 v->valid = 1;
1106 v->not_found = 0;
1107 v->no_cacheable = vv->no_cacheable;
1109 return NGX_OK;
1113 #if (NGX_HAVE_MD5)
1114 static ngx_int_t
1115 ngx_http_variable_md5(ngx_http_request_t *r, ngx_http_variable_value_t *v,
1116 uintptr_t data)
1118 ngx_str_t *name = (ngx_str_t *) data;
1120 ngx_str_t sub_name;
1121 ngx_uint_t key, i;
1122 ngx_md5_t md5;
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) {
1135 return NGX_ERROR;
1138 if (vv->not_found) {
1139 v->not_found = 1;
1140 return NGX_OK;
1143 v->len = sizeof("7002945D4B8D9E472866092689DB3EAD") - 1;
1145 v->data = ngx_palloc(r->pool, v->len);
1146 if (v->data == NULL) {
1147 v->not_found = 1;
1148 return NGX_OK;
1151 ngx_md5_init(&md5);
1152 ngx_md5_update(&md5, vv->data, vv->len);
1153 ngx_md5_final((u_char*)hash, &md5);
1155 p = v->data;
1157 for (i = 0; i < 16; i++) {
1158 p = ngx_sprintf(p, "%02XD", hash[i]);
1161 v->valid = 1;
1162 v->not_found = 0;
1163 v->no_cacheable = vv->no_cacheable;
1165 return NGX_OK;
1167 #endif
1170 static ngx_int_t
1171 ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v,
1172 uintptr_t data)
1174 ngx_str_t *name = (ngx_str_t *) data;
1176 u_char *arg;
1177 size_t len;
1178 ngx_str_t value;
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) {
1184 v->not_found = 1;
1185 return NGX_OK;
1188 v->data = value.data;
1189 v->len = value.len;
1190 v->valid = 1;
1191 v->no_cacheable = 0;
1192 v->not_found = 0;
1194 return NGX_OK;
1198 static ngx_int_t
1199 ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v,
1200 uintptr_t data)
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;
1208 } else {
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;
1215 v->valid = 1;
1216 v->no_cacheable = 0;
1217 v->not_found = 0;
1219 return NGX_OK;
1223 static ngx_int_t
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;
1230 #endif
1232 switch (r->connection->sockaddr->sa_family) {
1234 #if (NGX_HAVE_INET6)
1235 case AF_INET6:
1236 sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
1238 v->len = sizeof(struct in6_addr);
1239 v->valid = 1;
1240 v->no_cacheable = 0;
1241 v->not_found = 0;
1242 v->data = sin6->sin6_addr.s6_addr;
1244 break;
1245 #endif
1247 default: /* AF_INET */
1248 sin = (struct sockaddr_in *) r->connection->sockaddr;
1250 v->len = sizeof(in_addr_t);
1251 v->valid = 1;
1252 v->no_cacheable = 0;
1253 v->not_found = 0;
1254 v->data = (u_char *) &sin->sin_addr;
1256 break;
1259 return NGX_OK;
1263 static ngx_int_t
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;
1268 v->valid = 1;
1269 v->no_cacheable = 0;
1270 v->not_found = 0;
1271 v->data = r->connection->addr_text.data;
1273 return NGX_OK;
1277 static ngx_int_t
1278 ngx_http_variable_remote_port(ngx_http_request_t *r,
1279 ngx_http_variable_value_t *v, uintptr_t data)
1281 ngx_uint_t port;
1282 struct sockaddr_in *sin;
1283 #if (NGX_HAVE_INET6)
1284 struct sockaddr_in6 *sin6;
1285 #endif
1287 v->len = 0;
1288 v->valid = 1;
1289 v->no_cacheable = 0;
1290 v->not_found = 0;
1292 v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
1293 if (v->data == NULL) {
1294 return NGX_ERROR;
1297 switch (r->connection->sockaddr->sa_family) {
1299 #if (NGX_HAVE_INET6)
1300 case AF_INET6:
1301 sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
1302 port = ntohs(sin6->sin6_port);
1303 break;
1304 #endif
1306 default: /* AF_INET */
1307 sin = (struct sockaddr_in *) r->connection->sockaddr;
1308 port = ntohs(sin->sin_port);
1309 break;
1312 if (port > 0 && port < 65536) {
1313 v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
1316 return NGX_OK;
1320 static ngx_int_t
1321 ngx_http_variable_server_addr(ngx_http_request_t *r,
1322 ngx_http_variable_value_t *v, uintptr_t data)
1324 ngx_str_t s;
1325 u_char addr[NGX_SOCKADDR_STRLEN];
1327 s.len = NGX_SOCKADDR_STRLEN;
1328 s.data = addr;
1330 if (ngx_connection_local_sockaddr(r->connection, &s, 0) != NGX_OK) {
1331 return NGX_ERROR;
1334 s.data = ngx_pnalloc(r->pool, s.len);
1335 if (s.data == NULL) {
1336 return NGX_ERROR;
1339 ngx_memcpy(s.data, addr, s.len);
1341 v->len = s.len;
1342 v->valid = 1;
1343 v->no_cacheable = 0;
1344 v->not_found = 0;
1345 v->data = s.data;
1347 return NGX_OK;
1351 static ngx_int_t
1352 ngx_http_variable_server_port(ngx_http_request_t *r,
1353 ngx_http_variable_value_t *v, uintptr_t data)
1355 ngx_uint_t port;
1356 struct sockaddr_in *sin;
1357 #if (NGX_HAVE_INET6)
1358 struct sockaddr_in6 *sin6;
1359 #endif
1361 v->len = 0;
1362 v->valid = 1;
1363 v->no_cacheable = 0;
1364 v->not_found = 0;
1366 if (ngx_connection_local_sockaddr(r->connection, NULL, 0) != NGX_OK) {
1367 return NGX_ERROR;
1370 v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
1371 if (v->data == NULL) {
1372 return NGX_ERROR;
1375 switch (r->connection->local_sockaddr->sa_family) {
1377 #if (NGX_HAVE_INET6)
1378 case AF_INET6:
1379 sin6 = (struct sockaddr_in6 *) r->connection->local_sockaddr;
1380 port = ntohs(sin6->sin6_port);
1381 break;
1382 #endif
1384 default: /* AF_INET */
1385 sin = (struct sockaddr_in *) r->connection->local_sockaddr;
1386 port = ntohs(sin->sin_port);
1387 break;
1390 if (port > 0 && port < 65536) {
1391 v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
1394 return NGX_OK;
1398 static ngx_int_t
1399 ngx_http_variable_scheme(ngx_http_request_t *r,
1400 ngx_http_variable_value_t *v, uintptr_t data)
1402 #if (NGX_HTTP_SSL)
1404 if (r->connection->ssl) {
1405 v->len = sizeof("https") - 1;
1406 v->valid = 1;
1407 v->no_cacheable = 0;
1408 v->not_found = 0;
1409 v->data = (u_char *) "https";
1411 return NGX_OK;
1414 #endif
1416 v->len = sizeof("http") - 1;
1417 v->valid = 1;
1418 v->no_cacheable = 0;
1419 v->not_found = 0;
1420 v->data = (u_char *) "http";
1422 return NGX_OK;
1426 static ngx_int_t
1427 ngx_http_variable_is_args(ngx_http_request_t *r,
1428 ngx_http_variable_value_t *v, uintptr_t data)
1430 v->valid = 1;
1431 v->no_cacheable = 0;
1432 v->not_found = 0;
1434 if (r->args.len == 0) {
1435 v->len = 0;
1436 v->data = NULL;
1437 return NGX_OK;
1440 v->len = 1;
1441 v->data = (u_char *) "?";
1443 return NGX_OK;
1447 static ngx_int_t
1448 ngx_http_variable_document_root(ngx_http_request_t *r,
1449 ngx_http_variable_value_t *v, uintptr_t data)
1451 ngx_str_t path;
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;
1458 v->valid = 1;
1459 v->no_cacheable = 0;
1460 v->not_found = 0;
1461 v->data = clcf->root.data;
1463 } else {
1464 if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 0,
1465 clcf->root_values->elts)
1466 == NULL)
1468 return NGX_ERROR;
1471 if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
1472 return NGX_ERROR;
1475 v->len = path.len;
1476 v->valid = 1;
1477 v->no_cacheable = 0;
1478 v->not_found = 0;
1479 v->data = path.data;
1482 return NGX_OK;
1486 static ngx_int_t
1487 ngx_http_variable_realpath_root(ngx_http_request_t *r,
1488 ngx_http_variable_value_t *v, uintptr_t data)
1490 size_t len;
1491 ngx_str_t path;
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) {
1498 path = clcf->root;
1500 } else {
1501 if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 1,
1502 clcf->root_values->elts)
1503 == NULL)
1505 return NGX_ERROR;
1508 path.data[path.len - 1] = '\0';
1510 if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
1511 return NGX_ERROR;
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);
1518 return NGX_ERROR;
1521 len = ngx_strlen(real);
1523 v->data = ngx_pnalloc(r->pool, len);
1524 if (v->data == NULL) {
1525 return NGX_ERROR;
1528 v->len = len;
1529 v->valid = 1;
1530 v->no_cacheable = 0;
1531 v->not_found = 0;
1533 ngx_memcpy(v->data, real, len);
1535 return NGX_OK;
1539 static ngx_int_t
1540 ngx_http_variable_request_filename(ngx_http_request_t *r,
1541 ngx_http_variable_value_t *v, uintptr_t data)
1543 size_t root;
1544 ngx_str_t path;
1546 if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
1547 return NGX_ERROR;
1550 /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */
1552 v->len = path.len - 1;
1553 v->valid = 1;
1554 v->no_cacheable = 0;
1555 v->not_found = 0;
1556 v->data = path.data;
1558 return NGX_OK;
1562 static ngx_int_t
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;
1571 v->valid = 1;
1572 v->no_cacheable = 0;
1573 v->not_found = 0;
1574 v->data = cscf->server_name.data;
1576 return NGX_OK;
1580 static ngx_int_t
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;
1586 v->valid = 1;
1587 v->no_cacheable = 0;
1588 v->not_found = 0;
1589 v->data = r->main->method_name.data;
1591 } else {
1592 v->not_found = 1;
1595 return NGX_OK;
1599 static ngx_int_t
1600 ngx_http_variable_remote_user(ngx_http_request_t *r,
1601 ngx_http_variable_value_t *v, uintptr_t data)
1603 ngx_int_t rc;
1605 rc = ngx_http_auth_basic_user(r);
1607 if (rc == NGX_DECLINED) {
1608 v->not_found = 1;
1609 return NGX_OK;
1612 if (rc == NGX_ERROR) {
1613 return NGX_ERROR;
1616 v->len = r->headers_in.user.len;
1617 v->valid = 1;
1618 v->no_cacheable = 0;
1619 v->not_found = 0;
1620 v->data = r->headers_in.user.data;
1622 return NGX_OK;
1626 static ngx_int_t
1627 ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
1628 ngx_http_variable_value_t *v, uintptr_t data)
1630 off_t sent;
1631 u_char *p;
1633 sent = r->connection->sent - r->header_size;
1635 if (sent < 0) {
1636 sent = 0;
1639 p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
1640 if (p == NULL) {
1641 return NGX_ERROR;
1644 v->len = ngx_sprintf(p, "%O", sent) - p;
1645 v->valid = 1;
1646 v->no_cacheable = 0;
1647 v->not_found = 0;
1648 v->data = p;
1650 return NGX_OK;
1654 static ngx_int_t
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;
1660 v->valid = 1;
1661 v->no_cacheable = 0;
1662 v->not_found = 0;
1663 v->data = r->headers_out.content_type.data;
1665 } else {
1666 v->not_found = 1;
1669 return NGX_OK;
1673 static ngx_int_t
1674 ngx_http_variable_sent_content_length(ngx_http_request_t *r,
1675 ngx_http_variable_value_t *v, uintptr_t data)
1677 u_char *p;
1679 if (r->headers_out.content_length) {
1680 v->len = r->headers_out.content_length->value.len;
1681 v->valid = 1;
1682 v->no_cacheable = 0;
1683 v->not_found = 0;
1684 v->data = r->headers_out.content_length->value.data;
1686 return NGX_OK;
1689 if (r->headers_out.content_length_n >= 0) {
1690 p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
1691 if (p == NULL) {
1692 return NGX_ERROR;
1695 v->len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) - p;
1696 v->valid = 1;
1697 v->no_cacheable = 0;
1698 v->not_found = 0;
1699 v->data = p;
1701 return NGX_OK;
1704 v->not_found = 1;
1706 return NGX_OK;
1710 static ngx_int_t
1711 ngx_http_variable_sent_location(ngx_http_request_t *r,
1712 ngx_http_variable_value_t *v, uintptr_t data)
1714 ngx_str_t name;
1716 if (r->headers_out.location) {
1717 v->len = r->headers_out.location->value.len;
1718 v->valid = 1;
1719 v->no_cacheable = 0;
1720 v->not_found = 0;
1721 v->data = r->headers_out.location->value.data;
1723 return NGX_OK;
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);
1734 static ngx_int_t
1735 ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
1736 ngx_http_variable_value_t *v, uintptr_t data)
1738 u_char *p;
1740 if (r->headers_out.last_modified) {
1741 v->len = r->headers_out.last_modified->value.len;
1742 v->valid = 1;
1743 v->no_cacheable = 0;
1744 v->not_found = 0;
1745 v->data = r->headers_out.last_modified->value.data;
1747 return NGX_OK;
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);
1753 if (p == NULL) {
1754 return NGX_ERROR;
1757 v->len = ngx_http_time(p, r->headers_out.last_modified_time) - p;
1758 v->valid = 1;
1759 v->no_cacheable = 0;
1760 v->not_found = 0;
1761 v->data = p;
1763 return NGX_OK;
1766 v->not_found = 1;
1768 return NGX_OK;
1772 static ngx_int_t
1773 ngx_http_variable_sent_etag(ngx_http_request_t *r,
1774 ngx_http_variable_value_t *v, uintptr_t data)
1776 u_char *p;
1778 if (r->headers_out.etag) {
1779 v->len = r->headers_out.etag->value.len;
1780 v->valid = 1;
1781 v->no_cacheable = 0;
1782 v->not_found = 0;
1783 v->data = r->headers_out.etag->value.data;
1785 return NGX_OK;
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);
1794 if (p == NULL) {
1795 return NGX_ERROR;
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;
1802 v->valid = 1;
1803 v->no_cacheable = 0;
1804 v->not_found = 0;
1805 v->data = p;
1807 return NGX_OK;
1810 v->not_found = 1;
1812 return NGX_OK;
1816 static ngx_int_t
1817 ngx_http_variable_sent_connection(ngx_http_request_t *r,
1818 ngx_http_variable_value_t *v, uintptr_t data)
1820 size_t len;
1821 char *p;
1823 if (r->keepalive) {
1824 len = sizeof("keep-alive") - 1;
1825 p = "keep-alive";
1827 } else {
1828 len = sizeof("close") - 1;
1829 p = "close";
1832 v->len = len;
1833 v->valid = 1;
1834 v->no_cacheable = 0;
1835 v->not_found = 0;
1836 v->data = (u_char *) p;
1838 return NGX_OK;
1842 static ngx_int_t
1843 ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
1844 ngx_http_variable_value_t *v, uintptr_t data)
1846 u_char *p;
1847 ngx_http_core_loc_conf_t *clcf;
1849 if (r->keepalive) {
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);
1855 if (p == NULL) {
1856 return NGX_ERROR;
1859 v->len = ngx_sprintf(p, "timeout=%T", clcf->keepalive_header) - p;
1860 v->valid = 1;
1861 v->no_cacheable = 0;
1862 v->not_found = 0;
1863 v->data = p;
1865 return NGX_OK;
1869 v->not_found = 1;
1871 return NGX_OK;
1875 static ngx_int_t
1876 ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
1877 ngx_http_variable_value_t *v, uintptr_t data)
1879 if (r->chunked) {
1880 v->len = sizeof("chunked") - 1;
1881 v->valid = 1;
1882 v->no_cacheable = 0;
1883 v->not_found = 0;
1884 v->data = (u_char *) "chunked";
1886 } else {
1887 v->not_found = 1;
1890 return NGX_OK;
1894 static ngx_int_t
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) {
1899 v->len = 2;
1900 v->valid = 1;
1901 v->no_cacheable = 0;
1902 v->not_found = 0;
1903 v->data = (u_char *) "OK";
1905 return NGX_OK;
1908 v->len = 0;
1909 v->valid = 1;
1910 v->no_cacheable = 0;
1911 v->not_found = 0;
1912 v->data = (u_char *) "";
1914 return NGX_OK;
1918 static ngx_int_t
1919 ngx_http_variable_request_body(ngx_http_request_t *r,
1920 ngx_http_variable_value_t *v, uintptr_t data)
1922 u_char *p;
1923 size_t len;
1924 ngx_buf_t *buf, *next;
1925 ngx_chain_t *cl;
1927 if (r->request_body == NULL
1928 || r->request_body->bufs == NULL
1929 || r->request_body->temp_file)
1931 v->not_found = 1;
1933 return NGX_OK;
1936 cl = r->request_body->bufs;
1937 buf = cl->buf;
1939 if (cl->next == NULL) {
1940 v->len = buf->last - buf->pos;
1941 v->valid = 1;
1942 v->no_cacheable = 0;
1943 v->not_found = 0;
1944 v->data = buf->pos;
1946 return NGX_OK;
1949 next = cl->next->buf;
1950 len = (buf->last - buf->pos) + (next->last - next->pos);
1952 p = ngx_pnalloc(r->pool, len);
1953 if (p == NULL) {
1954 return NGX_ERROR;
1957 v->data = p;
1959 p = ngx_cpymem(p, buf->pos, buf->last - buf->pos);
1960 ngx_memcpy(p, next->pos, next->last - next->pos);
1962 v->len = len;
1963 v->valid = 1;
1964 v->no_cacheable = 0;
1965 v->not_found = 0;
1967 return NGX_OK;
1971 static ngx_int_t
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) {
1976 v->not_found = 1;
1978 return NGX_OK;
1981 v->len = r->request_body->temp_file->file.name.len;
1982 v->valid = 1;
1983 v->no_cacheable = 0;
1984 v->not_found = 0;
1985 v->data = r->request_body->temp_file->file.name.data;
1987 return NGX_OK;
1991 static ngx_int_t
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;
1996 v->valid = 1;
1997 v->no_cacheable = 0;
1998 v->not_found = 0;
1999 v->data = (u_char *) NGINX_VERSION;
2001 return NGX_OK;
2005 static ngx_int_t
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;
2010 v->valid = 1;
2011 v->no_cacheable = 0;
2012 v->not_found = 0;
2013 v->data = ngx_cycle->hostname.data;
2015 return NGX_OK;
2019 static ngx_int_t
2020 ngx_http_variable_pid(ngx_http_request_t *r,
2021 ngx_http_variable_value_t *v, uintptr_t data)
2023 u_char *p;
2025 p = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
2026 if (p == NULL) {
2027 return NGX_ERROR;
2030 v->len = ngx_sprintf(p, "%P", ngx_pid) - p;
2031 v->valid = 1;
2032 v->no_cacheable = 0;
2033 v->not_found = 0;
2034 v->data = p;
2036 return NGX_OK;
2039 static ngx_int_t
2040 ngx_http_variable_timestamp(ngx_http_request_t *r,
2041 ngx_http_variable_value_t *v, uintptr_t data)
2043 u_char *p;
2045 p = ngx_pnalloc(r->pool, NGX_INT64_LEN);
2046 if (p == NULL) {
2047 return NGX_ERROR;
2050 v->len = ngx_sprintf(p, "%T", ngx_time()) - p;
2051 v->valid = 1;
2052 v->no_cacheable = 0;
2053 v->not_found = 0;
2054 v->data = p;
2056 return NGX_OK;
2060 static ngx_int_t
2061 ngx_http_variable_mstimestamp(ngx_http_request_t *r,
2062 ngx_http_variable_value_t *v, uintptr_t data)
2064 u_char *p;
2066 p = ngx_pnalloc(r->pool, NGX_INT64_LEN + sizeof("123") - 1);
2067 if (p == NULL) {
2068 return NGX_ERROR;
2071 v->len = ngx_sprintf(p, "%T%03M", ngx_time(), (ngx_timeofday())->msec) - p;
2072 v->valid = 1;
2073 v->no_cacheable = 0;
2074 v->not_found = 0;
2075 v->data = p;
2077 return NGX_OK;
2081 static ngx_int_t
2082 ngx_http_variable_loadavg_1m(ngx_http_request_t *r,
2083 ngx_http_variable_value_t *v, uintptr_t data)
2085 u_char *p;
2086 ngx_int_t la;
2088 p = ngx_pnalloc(r->pool, NGX_INT64_LEN);
2089 if (p == NULL) {
2090 return NGX_ERROR;
2093 la = ngx_get_loadavg(0);
2094 if (la == NGX_ERROR) {
2095 return NGX_ERROR;
2098 v->len = ngx_sprintf(p, "%i", la) - p;
2099 v->valid = 1;
2100 v->no_cacheable = 1;
2101 v->not_found = 0;
2102 v->data = p;
2104 return NGX_OK;
2108 static ngx_int_t
2109 ngx_http_variable_loadavg_5m(ngx_http_request_t *r,
2110 ngx_http_variable_value_t *v, uintptr_t data)
2112 u_char *p;
2113 ngx_int_t la;
2115 p = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
2116 if (p == NULL) {
2117 return NGX_ERROR;
2120 la = ngx_get_loadavg(1);
2121 if (la == NGX_ERROR) {
2122 return NGX_ERROR;
2125 v->len = ngx_sprintf(p, "%i", la) - p;
2126 v->valid = 1;
2127 v->no_cacheable = 1;
2128 v->not_found = 0;
2129 v->data = p;
2131 return NGX_OK;
2135 static ngx_int_t
2136 ngx_http_variable_loadavg_15m(ngx_http_request_t *r,
2137 ngx_http_variable_value_t *v, uintptr_t data)
2139 u_char *p;
2140 ngx_int_t la;
2142 p = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
2143 if (p == NULL) {
2144 return NGX_ERROR;
2147 la = ngx_get_loadavg(2);
2148 if (la == NGX_ERROR) {
2149 return NGX_ERROR;
2152 v->len = ngx_sprintf(p, "%i", la) - p;
2153 v->valid = 1;
2154 v->no_cacheable = 1;
2155 v->not_found = 0;
2156 v->data = p;
2158 return NGX_OK;
2162 #if (NGX_PCRE)
2164 static ngx_int_t
2165 ngx_http_variable_not_found(ngx_http_request_t *r, ngx_http_variable_value_t *v,
2166 uintptr_t data)
2168 v->not_found = 1;
2169 return NGX_OK;
2173 ngx_http_regex_t *
2174 ngx_http_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc)
2176 u_char *p;
2177 size_t size;
2178 ngx_str_t name;
2179 ngx_uint_t i, n;
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);
2189 return NULL;
2192 re = ngx_pcalloc(cf->pool, sizeof(ngx_http_regex_t));
2193 if (re == NULL) {
2194 return NULL;
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;
2205 if (n == 0) {
2206 return re;
2209 rv = ngx_palloc(rc->pool, n * sizeof(ngx_http_regex_variable_t));
2210 if (rv == NULL) {
2211 return NULL;
2214 re->variables = rv;
2215 re->nvariables = n;
2216 re->name = rc->pattern;
2218 size = rc->name_size;
2219 p = rc->names;
2221 for (i = 0; i < n; i++) {
2222 rv[i].capture = 2 * ((p[0] << 8) + p[1]);
2224 name.data = &p[2];
2225 name.len = ngx_strlen(name.data);
2227 v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
2228 if (v == NULL) {
2229 return NULL;
2232 rv[i].index = ngx_http_get_variable_index(cf, &name);
2233 if (rv[i].index == NGX_ERROR) {
2234 return NULL;
2237 v->get_handler = ngx_http_variable_not_found;
2239 p += size;
2242 return re;
2246 ngx_int_t
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) {
2262 return NGX_ERROR;
2266 } else {
2267 len = 0;
2270 rc = ngx_regex_exec(re->regex, s, r->captures, len);
2272 if (rc == NGX_REGEX_NO_MATCHED) {
2273 return NGX_DECLINED;
2276 if (rc < 0) {
2277 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
2278 ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
2279 rc, s, &re->name);
2280 return NGX_ERROR;
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];
2290 vv->valid = 1;
2291 vv->no_cacheable = 0;
2292 vv->not_found = 0;
2293 vv->data = &s->data[r->captures[n]];
2295 #if (NGX_DEBUG)
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);
2305 #endif
2308 r->ncaptures = rc * 2;
2309 r->captures_data = s->data;
2311 return NGX_OK;
2314 #endif
2317 ngx_int_t
2318 ngx_http_variables_add_core_vars(ngx_conf_t *cf)
2320 ngx_int_t rc;
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) {
2329 return NGX_ERROR;
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)
2336 != NGX_OK)
2338 return NGX_ERROR;
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);
2345 if (rc == NGX_OK) {
2346 continue;
2349 if (rc == NGX_BUSY) {
2350 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2351 "conflicting variable name \"%V\"", &v->name);
2354 return NGX_ERROR;
2357 return NGX_OK;
2361 ngx_int_t
2362 ngx_http_variables_init_vars(ngx_conf_t *cf)
2364 ngx_uint_t i, n;
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++) {
2381 av = key[n].value;
2383 if (av->get_handler
2384 && v[i].name.len == key[n].key.len
2385 && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len)
2386 == 0)
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;
2394 av->index = i;
2396 goto next;
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;
2404 continue;
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;
2411 continue;
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;
2419 continue;
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;
2426 continue;
2429 #if (NGX_HTTP_SSI)
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;
2434 continue;
2436 #endif
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;
2442 continue;
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;
2449 continue;
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;
2456 continue;
2459 #if (NGX_HAVE_MD5)
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;
2464 continue;
2466 #endif
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;
2473 continue;
2476 ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
2477 "unknown \"%V\" variable", &v[i].name);
2479 return NGX_ERROR;
2481 next:
2482 continue;
2486 for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {
2487 av = key[n].value;
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)
2505 != NGX_OK)
2507 return NGX_ERROR;
2510 cmcf->variables_keys = NULL;
2512 return NGX_OK;
2516 void
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;
2523 for ( ;; ) {
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;
2536 } else {
2537 p = (ngx_memcmp(vvn->value->data, vvt->value->data, vvn->len) < 0)
2538 ? &temp->left : &temp->right;
2541 if (*p == sentinel) {
2542 break;
2545 temp = *p;
2548 *p = node;
2549 node->parent = temp;
2550 node->left = sentinel;
2551 node->right = sentinel;
2552 ngx_rbt_red(node);
2556 ngx_http_variable_value_t *
2557 ngx_http_variable_value_lookup(ngx_rbtree_t *rbtree, ngx_str_t *val,
2558 uint32_t hash)
2560 ngx_int_t rc;
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;
2573 continue;
2576 if (val->len != vvn->len) {
2577 node = (val->len < vvn->len) ? node->left : node->right;
2578 continue;
2581 rc = ngx_memcmp(val->data, vvn->value->data, val->len);
2583 if (rc < 0) {
2584 node = node->left;
2585 continue;
2588 if (rc > 0) {
2589 node = node->right;
2590 continue;
2593 return vvn->value;
2596 return NULL;