~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/ngx_http_variables.c

Version: ~ [ nginx-0.8.20 ] ~ [ nginx-0.7.62 ] ~ [ nginx-0.6.39 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  */
  5 
  6 
  7 #include <ngx_config.h>
  8 #include <ngx_core.h>
  9 #include <ngx_http.h>
 10 #include <nginx.h>
 11 
 12 
 13 static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r,
 14     ngx_http_variable_value_t *v, uintptr_t data);
 15 static void ngx_http_variable_request_set(ngx_http_request_t *r,
 16     ngx_http_variable_value_t *v, uintptr_t data);
 17 static void ngx_http_variable_request_set_size(ngx_http_request_t *r,
 18     ngx_http_variable_value_t *v, uintptr_t data);
 19 static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r,
 20     ngx_http_variable_value_t *v, uintptr_t data);
 21 static ngx_int_t ngx_http_variable_headers(ngx_http_request_t *r,
 22     ngx_http_variable_value_t *v, uintptr_t data);
 23 
 24 static ngx_int_t ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
 25     ngx_http_variable_value_t *v, uintptr_t data);
 26 static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
 27     ngx_http_variable_value_t *v, uintptr_t data);
 28 static ngx_int_t ngx_http_variable_request_line(ngx_http_request_t *r,
 29     ngx_http_variable_value_t *v, uintptr_t data);
 30 static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r,
 31     ngx_http_variable_value_t *v, uintptr_t data);
 32 static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r,
 33     ngx_http_variable_value_t *v, uintptr_t data);
 34 
 35 static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r,
 36     ngx_http_variable_value_t *v, uintptr_t data);
 37 static ngx_int_t ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
 38     ngx_http_variable_value_t *v, uintptr_t data);
 39 static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r,
 40     ngx_http_variable_value_t *v, uintptr_t data);
 41 static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r,
 42     ngx_http_variable_value_t *v, uintptr_t data);
 43 static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r,
 44     ngx_http_variable_value_t *v, uintptr_t data);
 45 static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
 46     ngx_http_variable_value_t *v, uintptr_t data);
 47 static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r,
 48     ngx_http_variable_value_t *v, uintptr_t data);
 49 static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r,
 50     ngx_http_variable_value_t *v, uintptr_t data);
 51 static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r,
 52     ngx_http_variable_value_t *v, uintptr_t data);
 53 static ngx_int_t ngx_http_variable_realpath_root(ngx_http_request_t *r,
 54     ngx_http_variable_value_t *v, uintptr_t data);
 55 static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r,
 56     ngx_http_variable_value_t *v, uintptr_t data);
 57 static ngx_int_t ngx_http_variable_server_name(ngx_http_request_t *r,
 58     ngx_http_variable_value_t *v, uintptr_t data);
 59 static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r,
 60     ngx_http_variable_value_t *v, uintptr_t data);
 61 static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r,
 62     ngx_http_variable_value_t *v, uintptr_t data);
 63 static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
 64     ngx_http_variable_value_t *v, uintptr_t data);
 65 static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
 66     ngx_http_variable_value_t *v, uintptr_t data);
 67 static ngx_int_t ngx_http_variable_request_body(ngx_http_request_t *r,
 68     ngx_http_variable_value_t *v, uintptr_t data);
 69 static ngx_int_t ngx_http_variable_request_body_file(ngx_http_request_t *r,
 70     ngx_http_variable_value_t *v, uintptr_t data);
 71 
 72 static ngx_int_t ngx_http_variable_sent_content_type(ngx_http_request_t *r,
 73     ngx_http_variable_value_t *v, uintptr_t data);
 74 static ngx_int_t ngx_http_variable_sent_content_length(ngx_http_request_t *r,
 75     ngx_http_variable_value_t *v, uintptr_t data);
 76 static ngx_int_t ngx_http_variable_sent_location(ngx_http_request_t *r,
 77     ngx_http_variable_value_t *v, uintptr_t data);
 78 static ngx_int_t ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
 79     ngx_http_variable_value_t *v, uintptr_t data);
 80 static ngx_int_t ngx_http_variable_sent_connection(ngx_http_request_t *r,
 81     ngx_http_variable_value_t *v, uintptr_t data);
 82 static ngx_int_t ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
 83     ngx_http_variable_value_t *v, uintptr_t data);
 84 static ngx_int_t ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
 85     ngx_http_variable_value_t *v, uintptr_t data);
 86 
 87 static ngx_int_t ngx_http_variable_nginx_version(ngx_http_request_t *r,
 88     ngx_http_variable_value_t *v, uintptr_t data);
 89 static ngx_int_t ngx_http_variable_hostname(ngx_http_request_t *r,
 90     ngx_http_variable_value_t *v, uintptr_t data);
 91 static ngx_int_t ngx_http_variable_pid(ngx_http_request_t *r,
 92     ngx_http_variable_value_t *v, uintptr_t data);
 93 
 94 /*
 95  * TODO:
 96  *     Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED
 97  *                 REMOTE_HOST (null), REMOTE_IDENT (null),
 98  *                 SERVER_SOFTWARE
 99  *
100  *     Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner)
101  */
102 
103 /*
104  * the $http_host, $http_user_agent, $http_referer, $http_via,
105  * and $http_x_forwarded_for variables may be handled by generic
106  * ngx_http_variable_unknown_header_in(), but for perfomance reasons
107  * they are handled using dedicated entries
108  */
109 
110 static ngx_http_variable_t  ngx_http_core_variables[] = {
111 
112     { ngx_string("http_host"), NULL, ngx_http_variable_header,
113       offsetof(ngx_http_request_t, headers_in.host), 0, 0 },
114 
115     { ngx_string("http_user_agent"), NULL, ngx_http_variable_header,
116       offsetof(ngx_http_request_t, headers_in.user_agent), 0, 0 },
117 
118     { ngx_string("http_referer"), NULL, ngx_http_variable_header,
119       offsetof(ngx_http_request_t, headers_in.referer), 0, 0 },
120 
121 #if (NGX_HTTP_GZIP)
122     { ngx_string("http_via"), NULL, ngx_http_variable_header,
123       offsetof(ngx_http_request_t, headers_in.via), 0, 0 },
124 #endif
125 
126 #if (NGX_HTTP_PROXY || NGX_HTTP_REALIP)
127     { ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_header,
128       offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 },
129 #endif
130 
131     { ngx_string("http_cookie"), NULL, ngx_http_variable_headers,
132       offsetof(ngx_http_request_t, headers_in.cookies), 0, 0 },
133 
134     { ngx_string("content_length"), NULL, ngx_http_variable_header,
135       offsetof(ngx_http_request_t, headers_in.content_length), 0, 0 },
136 
137     { ngx_string("content_type"), NULL, ngx_http_variable_header,
138       offsetof(ngx_http_request_t, headers_in.content_type), 0, 0 },
139 
140     { ngx_string("host"), NULL, ngx_http_variable_host, 0, 0, 0 },
141 
142     { ngx_string("binary_remote_addr"), NULL,
143       ngx_http_variable_binary_remote_addr, 0, 0, 0 },
144 
145     { ngx_string("remote_addr"), NULL, ngx_http_variable_remote_addr, 0, 0, 0 },
146 
147     { ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 },
148 
149     { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },
150 
151     { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 },
152 
153     { ngx_string("server_protocol"), NULL, ngx_http_variable_request,
154       offsetof(ngx_http_request_t, http_protocol), 0, 0 },
155 
156     { ngx_string("scheme"), NULL, ngx_http_variable_scheme, 0, 0, 0 },
157 
158     { ngx_string("request_uri"), NULL, ngx_http_variable_request,
159       offsetof(ngx_http_request_t, unparsed_uri), 0, 0 },
160 
161     { ngx_string("uri"), NULL, ngx_http_variable_request,
162       offsetof(ngx_http_request_t, uri),
163       NGX_HTTP_VAR_NOCACHEABLE, 0 },
164 
165     { ngx_string("document_uri"), NULL, ngx_http_variable_request,
166       offsetof(ngx_http_request_t, uri),
167       NGX_HTTP_VAR_NOCACHEABLE, 0 },
168 
169     { ngx_string("request"), NULL, ngx_http_variable_request_line, 0, 0, 0 },
170 
171     { ngx_string("document_root"), NULL,
172       ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
173 
174     { ngx_string("realpath_root"), NULL,
175       ngx_http_variable_realpath_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
176 
177     { ngx_string("query_string"), NULL, ngx_http_variable_request,
178       offsetof(ngx_http_request_t, args),
179       NGX_HTTP_VAR_NOCACHEABLE, 0 },
180 
181     { ngx_string("args"),
182       ngx_http_variable_request_set,
183       ngx_http_variable_request,
184       offsetof(ngx_http_request_t, args),
185       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
186 
187     { ngx_string("is_args"), NULL, ngx_http_variable_is_args,
188       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
189 
190     { ngx_string("request_filename"), NULL,
191       ngx_http_variable_request_filename, 0,
192       NGX_HTTP_VAR_NOCACHEABLE, 0 },
193 
194     { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 },
195 
196     { ngx_string("request_method"), NULL,
197       ngx_http_variable_request_method, 0, 0, 0 },
198 
199     { ngx_string("remote_user"), NULL, ngx_http_variable_remote_user, 0, 0, 0 },
200 
201     { ngx_string("body_bytes_sent"), NULL, ngx_http_variable_body_bytes_sent,
202       0, 0, 0 },
203 
204     { ngx_string("request_completion"), NULL,
205       ngx_http_variable_request_completion,
206       0, 0, 0 },
207 
208     { ngx_string("request_body"), NULL,
209       ngx_http_variable_request_body,
210       0, 0, 0 },
211 
212     { ngx_string("request_body_file"), NULL,
213       ngx_http_variable_request_body_file,
214       0, 0, 0 },
215 
216     { ngx_string("sent_http_content_type"), NULL,
217       ngx_http_variable_sent_content_type, 0, 0, 0 },
218 
219     { ngx_string("sent_http_content_length"), NULL,
220       ngx_http_variable_sent_content_length, 0, 0, 0 },
221 
222     { ngx_string("sent_http_location"), NULL,
223       ngx_http_variable_sent_location, 0, 0, 0 },
224 
225     { ngx_string("sent_http_last_modified"), NULL,
226       ngx_http_variable_sent_last_modified, 0, 0, 0 },
227 
228     { ngx_string("sent_http_connection"), NULL,
229       ngx_http_variable_sent_connection, 0, 0, 0 },
230 
231     { ngx_string("sent_http_keep_alive"), NULL,
232       ngx_http_variable_sent_keep_alive, 0, 0, 0 },
233 
234     { ngx_string("sent_http_transfer_encoding"), NULL,
235       ngx_http_variable_sent_transfer_encoding, 0, 0, 0 },
236 
237     { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers,
238       offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 },
239 
240     { ngx_string("limit_rate"), ngx_http_variable_request_set_size,
241       ngx_http_variable_request,
242       offsetof(ngx_http_request_t, limit_rate),
243       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
244 
245     { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version,
246       0, 0, 0 },
247 
248     { ngx_string("hostname"), NULL, ngx_http_variable_hostname,
249       0, 0, 0 },
250 
251     { ngx_string("pid"), NULL, ngx_http_variable_pid,
252       0, 0, 0 },
253 
254     { ngx_null_string, NULL, NULL, 0, 0, 0 }
255 };
256 
257 
258 ngx_http_variable_value_t  ngx_http_variable_null_value =
259     ngx_http_variable("");
260 ngx_http_variable_value_t  ngx_http_variable_true_value =
261     ngx_http_variable("1");
262 
263 
264 ngx_http_variable_t *
265 ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
266 {
267     ngx_int_t                   rc;
268     ngx_uint_t                  i;
269     ngx_hash_key_t             *key;
270     ngx_http_variable_t        *v;
271     ngx_http_core_main_conf_t  *cmcf;
272 
273     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
274 
275     key = cmcf->variables_keys->keys.elts;
276     for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) {
277         if (name->len != key[i].key.len
278             || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0)
279         {
280             continue;
281         }
282 
283         v = key[i].value;
284 
285         if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
286             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
287                                "the duplicate \"%V\" variable", name);
288             return NULL;
289         }
290 
291         return v;
292     }
293 
294     v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));
295     if (v == NULL) {
296         return NULL;
297     }
298 
299     v->name.len = name->len;
300     v->name.data = ngx_pnalloc(cf->pool, name->len);
301     if (v->name.data == NULL) {
302         return NULL;
303     }
304 
305     ngx_strlow(v->name.data, name->data, name->len);
306 
307     v->set_handler = NULL;
308     v->get_handler = NULL;
309     v->data = 0;
310     v->flags = flags;
311     v->index = 0;
312 
313     rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0);
314 
315     if (rc == NGX_ERROR) {
316         return NULL;
317     }
318 
319     if (rc == NGX_BUSY) {
320         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
321                            "conflicting variable name \"%V\"", name);
322         return NULL;
323     }
324 
325     return v;
326 }
327 
328 
329 ngx_int_t
330 ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name)
331 {
332     ngx_uint_t                  i;
333     ngx_http_variable_t        *v;
334     ngx_http_core_main_conf_t  *cmcf;
335 
336     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
337 
338     v = cmcf->variables.elts;
339 
340     if (v == NULL) {
341         if (ngx_array_init(&cmcf->variables, cf->pool, 4,
342                            sizeof(ngx_http_variable_t))
343             != NGX_OK)
344         {
345             return NGX_ERROR;
346         }
347 
348     } else {
349         for (i = 0; i < cmcf->variables.nelts; i++) {
350             if (name->len != v[i].name.len
351                 || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0)
352             {
353                 continue;
354             }
355 
356             return i;
357         }
358     }
359 
360     v = ngx_array_push(&cmcf->variables);
361     if (v == NULL) {
362         return NGX_ERROR;
363     }
364 
365     v->name.len = name->len;
366     v->name.data = ngx_pnalloc(cf->pool, name->len);
367     if (v->name.data == NULL) {
368         return NGX_ERROR;
369     }
370 
371     ngx_strlow(v->name.data, name->data, name->len);
372 
373     v->set_handler = NULL;
374     v->get_handler = NULL;
375     v->data = 0;
376     v->flags = 0;
377     v->index = cmcf->variables.nelts - 1;
378 
379     return cmcf->variables.nelts - 1;
380 }
381 
382 
383 ngx_http_variable_value_t *
384 ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
385 {
386     ngx_http_variable_t        *v;
387     ngx_http_core_main_conf_t  *cmcf;
388 
389     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
390 
391     if (cmcf->variables.nelts <= index) {
392         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
393                       "unknown variable index: %d", index);
394         return NULL;
395     }
396 
397     if (r->variables[index].not_found || r->variables[index].valid) {
398         return &r->variables[index];
399     }
400 
401     v = cmcf->variables.elts;
402 
403     if (v[index].get_handler(r, &r->variables[index], v[index].data)
404         == NGX_OK)
405     {
406         if (v[index].flags & NGX_HTTP_VAR_NOCACHEABLE) {
407             r->variables[index].no_cacheable = 1;
408         }
409 
410         return &r->variables[index];
411     }
412 
413     r->variables[index].valid = 0;
414     r->variables[index].not_found = 1;
415 
416     return NULL;
417 }
418 
419 
420 ngx_http_variable_value_t *
421 ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index)
422 {
423     ngx_http_variable_value_t  *v;
424 
425     v = &r->variables[index];
426 
427     if (v->valid) {
428         if (!v->no_cacheable) {
429             return v;
430         }
431 
432         v->valid = 0;
433         v->not_found = 0;
434     }
435 
436     return ngx_http_get_indexed_variable(r, index);
437 }
438 
439 
440 ngx_http_variable_value_t *
441 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key,
442     ngx_uint_t nowarn)
443 {
444     ngx_http_variable_t        *v;
445     ngx_http_variable_value_t  *vv;
446     ngx_http_core_main_conf_t  *cmcf;
447 
448     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
449 
450     v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len);
451 
452     if (v) {
453         if (v->flags & NGX_HTTP_VAR_INDEXED) {
454             return ngx_http_get_indexed_variable(r, v->index);
455 
456         } else {
457 
458             vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
459 
460             if (vv && v->get_handler(r, vv, v->data) == NGX_OK) {
461                 return vv;
462             }
463 
464             return NULL;
465         }
466     }
467 
468     vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
469     if (vv == NULL) {
470         return NULL;
471     }
472 
473     if (ngx_strncmp(name->data, "http_", 5) == 0) {
474 
475         if (ngx_http_variable_unknown_header_in(r, vv, (uintptr_t) name)
476             == NGX_OK)
477         {
478             return vv;
479         }
480 
481         return NULL;
482     }
483 
484     if (ngx_strncmp(name->data, "sent_http_", 10) == 0) {
485 
486         if (ngx_http_variable_unknown_header_out(r, vv, (uintptr_t) name)
487             == NGX_OK)
488         {
489             return vv;
490         }
491 
492         return NULL;
493     }
494 
495     if (ngx_strncmp(name->data, "upstream_http_", 10) == 0) {
496 
497         if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name)
498             == NGX_OK)
499         {
500             return vv;
501         }
502 
503         return NULL;
504     }
505 
506     if (ngx_strncmp(name->data, "cookie_", 7) == 0) {
507 
508         if (ngx_http_variable_cookie(r, vv, (uintptr_t) name) == NGX_OK) {
509             return vv;
510         }
511 
512         return NULL;
513     }
514 
515     if (ngx_strncmp(name->data, "arg_", 4) == 0) {
516 
517         if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) {
518             return vv;
519         }
520 
521         return NULL;
522     }
523 
524     vv->not_found = 1;
525 
526     if (nowarn == 0) {
527         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
528                       "unknown \"%V\" variable", name);
529     }
530 
531     return vv;
532 }
533 
534 
535 static ngx_int_t
536 ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v,
537     uintptr_t data)
538 {
539     ngx_str_t  *s;
540 
541     s = (ngx_str_t *) ((char *) r + data);
542 
543     if (s->data) {
544         v->len = s->len;
545         v->valid = 1;
546         v->no_cacheable = 0;
547         v->not_found = 0;
548         v->data = s->data;
549 
550     } else {
551         v->not_found = 1;
552     }
553 
554     return NGX_OK;
555 }
556 
557 
558 static void
559 ngx_http_variable_request_set(ngx_http_request_t *r,
560     ngx_http_variable_value_t *v, uintptr_t data)
561 {
562     ngx_str_t  *s;
563 
564     s = (ngx_str_t *) ((char *) r + data);
565 
566     s->len = v->len;
567     s->data = v->data;
568 }
569 
570 
571 static void
572 ngx_http_variable_request_set_size(ngx_http_request_t *r,
573     ngx_http_variable_value_t *v, uintptr_t data)
574 {
575     ssize_t    s, *sp;
576     ngx_str_t  val;
577 
578     val.len = v->len;
579     val.data = v->data;
580 
581     s = ngx_parse_size(&val);
582 
583     if (s == NGX_ERROR) {
584         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
585                       "invalid size \"%V\"", &val);
586         return;
587     }
588 
589     sp = (ssize_t *) ((char *) r + data);
590 
591     *sp = s;
592 
593     return;
594 }
595 
596 
597 static ngx_int_t
598 ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v,
599     uintptr_t data)
600 {
601     ngx_table_elt_t  *h;
602 
603     h = *(ngx_table_elt_t **) ((char *) r + data);
604 
605     if (h) {
606         v->len = h->value.len;
607         v->valid = 1;
608         v->no_cacheable = 0;
609         v->not_found = 0;
610         v->data = h->value.data;
611 
612     } else {
613         v->not_found = 1;
614     }
615 
616     return NGX_OK;
617 }
618 
619 
620 static ngx_int_t
621 ngx_http_variable_headers(ngx_http_request_t *r, ngx_http_variable_value_t *v,
622     uintptr_t data)
623 {
624     ssize_t            len;
625     u_char            *p;
626     ngx_uint_t         i, n;
627     ngx_array_t       *a;
628     ngx_table_elt_t  **h;
629 
630     a = (ngx_array_t *) ((char *) r + data);
631 
632     n = a->nelts;
633 
634     if (n == 0) {
635         v->not_found = 1;
636         return NGX_OK;
637     }
638 
639     v->valid = 1;
640     v->no_cacheable = 0;
641     v->not_found = 0;
642 
643     h = a->elts;
644 
645     if (n == 1) {
646         v->len = (*h)->value.len;
647         v->data = (*h)->value.data;
648 
649         return NGX_OK;
650     }
651 
652     len = - (ssize_t) (sizeof("; ") - 1);
653 
654     for (i = 0; i < n; i++) {
655         len += h[i]->value.len + sizeof("; ") - 1;
656     }
657 
658     p = ngx_pnalloc(r->pool, len);
659     if (p == NULL) {
660         return NGX_ERROR;
661     }
662 
663     v->len = len;
664     v->data = p;
665 
666     for (i = 0; /* void */ ; i++) {
667         p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
668 
669         if (i == n - 1) {
670             break;
671         }
672 
673         *p++ = ';'; *p++ = ' ';
674     }
675 
676     return NGX_OK;
677 }
678 
679 
680 static ngx_int_t
681 ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
682     ngx_http_variable_value_t *v, uintptr_t data)
683 {
684     return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
685                                             &r->headers_in.headers.part,
686                                             sizeof("http_") - 1);
687 }
688 
689 
690 static ngx_int_t
691 ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
692     ngx_http_variable_value_t *v, uintptr_t data)
693 {
694     return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
695                                             &r->headers_out.headers.part,
696                                             sizeof("sent_http_") - 1);
697 }
698 
699 
700 ngx_int_t
701 ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var,
702     ngx_list_part_t *part, size_t prefix)
703 {
704     u_char            ch;
705     ngx_uint_t        i, n;
706     ngx_table_elt_t  *header;
707 
708     header = part->elts;
709 
710     for (i = 0; /* void */ ; i++) {
711 
712         if (i >= part->nelts) {
713             if (part->next == NULL) {
714                 break;
715             }
716 
717             part = part->next;
718             header = part->elts;
719             i = 0;
720         }
721 
722         for (n = 0; n + prefix < var->len && n < header[i].key.len; n++) {
723             ch = header[i].key.data[n];
724 
725             if (ch >= 'A' && ch <= 'Z') {
726                 ch |= 0x20;
727 
728             } else if (ch == '-') {
729                 ch = '_';
730             }
731 
732             if (var->data[n + prefix] != ch) {
733                 break;
734             }
735         }
736 
737         if (n + prefix == var->len && n == header[i].key.len) {
738             v->len = header[i].value.len;
739             v->valid = 1;
740             v->no_cacheable = 0;
741             v->not_found = 0;
742             v->data = header[i].value.data;
743 
744             return NGX_OK;
745         }
746     }
747 
748     v->not_found = 1;
749 
750     return NGX_OK;
751 }
752 
753 
754 static ngx_int_t
755 ngx_http_variable_request_line(ngx_http_request_t *r,
756     ngx_http_variable_value_t *v, uintptr_t data)
757 {
758     u_char  *p, *s;
759 
760     s = r->request_line.data;
761 
762     if (s == NULL) {
763         s = r->request_start;
764 
765         if (s == NULL) {
766             v->not_found = 1;
767             return NGX_OK;
768         }
769 
770         for (p = s; p < r->header_in->last; p++) {
771             if (*p == CR || *p == LF) {
772                 break;
773             }
774         }
775 
776         r->request_line.len = p - s;
777         r->request_line.data = s;
778     }
779 
780     v->len = r->request_line.len;
781     v->valid = 1;
782     v->no_cacheable = 0;
783     v->not_found = 0;
784     v->data = s;
785 
786     return NGX_OK;
787 }
788 
789 
790 static ngx_int_t
791 ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v,
792     uintptr_t data)
793 {
794     ngx_str_t *name = (ngx_str_t *) data;
795 
796     ngx_str_t  cookie, s;
797 
798     s.len = name->len - (sizeof("cookie_") - 1);
799     s.data = name->data + sizeof("cookie_") - 1;
800 
801     if (ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &s, &cookie)
802         == NGX_DECLINED)
803     {
804         v->not_found = 1;
805         return NGX_OK;
806     }
807 
808     v->len = cookie.len;
809     v->valid = 1;
810     v->no_cacheable = 0;
811     v->not_found = 0;
812     v->data = cookie.data;
813 
814     return NGX_OK;
815 }
816 
817 
818 static ngx_int_t
819 ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v,
820     uintptr_t data)
821 {
822     ngx_str_t *name = (ngx_str_t *) data;
823 
824     u_char     *arg;
825     size_t      len;
826     ngx_str_t   value;
827 
828     len = name->len - (sizeof("arg_") - 1);
829     arg = name->data + sizeof("arg_") - 1;
830 
831     if (ngx_http_arg(r, arg, len, &value) != NGX_OK) {
832         v->not_found = 1;
833         return NGX_OK;
834     }
835 
836     v->data = value.data;
837     v->len = value.len;
838     v->valid = 1;
839     v->no_cacheable = 0;
840     v->not_found = 0;
841 
842     return NGX_OK;
843 }
844 
845 
846 static ngx_int_t
847 ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v,
848     uintptr_t data)
849 {
850     ngx_http_core_srv_conf_t  *cscf;
851 
852     if (r->headers_in.server.len) {
853         v->len = r->headers_in.server.len;
854         v->data = r->headers_in.server.data;
855 
856     } else {
857         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
858 
859         v->len = cscf->server_name.len;
860         v->data = cscf->server_name.data;
861     }
862 
863     v->valid = 1;
864     v->no_cacheable = 0;
865     v->not_found = 0;
866 
867     return NGX_OK;
868 }
869 
870 
871 static ngx_int_t
872 ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
873     ngx_http_variable_value_t *v, uintptr_t data)
874 {
875     struct sockaddr_in   *sin;
876 #if (NGX_HAVE_INET6)
877     struct sockaddr_in6  *sin6;
878 #endif
879 
880     switch (r->connection->sockaddr->sa_family) {
881 
882 #if (NGX_HAVE_INET6)
883     case AF_INET6:
884         sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
885 
886         v->len = sizeof(struct in6_addr);
887         v->valid = 1;
888         v->no_cacheable = 0;
889         v->not_found = 0;
890         v->data = (u_char *) &sin6->sin6_addr;
891 
892         break;
893 #endif
894 
895     default: /* AF_INET */
896         sin = (struct sockaddr_in *) r->connection->sockaddr;
897 
898         v->len = sizeof(in_addr_t);
899         v->valid = 1;
900         v->no_cacheable = 0;
901         v->not_found = 0;
902         v->data = (u_char *) &sin->sin_addr;
903 
904         break;
905     }
906 
907     return NGX_OK;
908 }
909 
910 
911 static ngx_int_t
912 ngx_http_variable_remote_addr(ngx_http_request_t *r,
913     ngx_http_variable_value_t *v, uintptr_t data)
914 {
915     v->len = r->connection->addr_text.len;
916     v->valid = 1;
917     v->no_cacheable = 0;
918     v->not_found = 0;
919     v->data = r->connection->addr_text.data;
920 
921     return NGX_OK;
922 }
923 
924 
925 static ngx_int_t
926 ngx_http_variable_remote_port(ngx_http_request_t *r,
927     ngx_http_variable_value_t *v, uintptr_t data)
928 {
929     ngx_uint_t            port;
930     struct sockaddr_in   *sin;
931 #if (NGX_HAVE_INET6)
932     struct sockaddr_in6  *sin6;
933 #endif
934 
935     v->len = 0;
936     v->valid = 1;
937     v->no_cacheable = 0;
938     v->not_found = 0;
939 
940     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
941     if (v->data == NULL) {
942         return NGX_ERROR;
943     }
944 
945     switch (r->connection->sockaddr->sa_family) {
946 
947 #if (NGX_HAVE_INET6)
948     case AF_INET6:
949         sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
950         port = ntohs(sin6->sin6_port);
951         break;
952 #endif
953 
954     default: /* AF_INET */
955         sin = (struct sockaddr_in *) r->connection->sockaddr;
956         port = ntohs(sin->sin_port);
957         break;
958     }
959 
960     if (port > 0 && port < 65536) {
961         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
962     }
963 
964     return NGX_OK;
965 }
966 
967 
968 static ngx_int_t
969 ngx_http_variable_server_addr(ngx_http_request_t *r,
970     ngx_http_variable_value_t *v, uintptr_t data)
971 {
972     ngx_str_t  s;
973     u_char     addr[NGX_SOCKADDR_STRLEN];
974 
975     s.len = NGX_SOCKADDR_STRLEN;
976     s.data = addr;
977 
978     if (ngx_connection_local_sockaddr(r->connection, &s, 0) != NGX_OK) {
979         return NGX_ERROR;
980     }
981 
982     s.data = ngx_pnalloc(r->pool, s.len);
983     if (s.data == NULL) {
984         return NGX_ERROR;
985     }
986 
987     ngx_memcpy(s.data, addr, s.len);
988 
989     v->len = s.len;
990     v->valid = 1;
991     v->no_cacheable = 0;
992     v->not_found = 0;
993     v->data = s.data;
994 
995     return NGX_OK;
996 }
997 
998 
999 static ngx_int_t
1000 ngx_http_variable_server_port(ngx_http_request_t *r,
1001     ngx_http_variable_value_t *v, uintptr_t data)
1002 {
1003     ngx_uint_t            port;
1004     struct sockaddr_in   *sin;
1005 #if (NGX_HAVE_INET6)
1006     struct sockaddr_in6  *sin6;
1007 #endif
1008 
1009     v->len = 0;
1010     v->valid = 1;
1011     v->no_cacheable = 0;
1012     v->not_found = 0;
1013 
1014     if (ngx_connection_local_sockaddr(r->connection, NULL, 0) != NGX_OK) {
1015         return NGX_ERROR;
1016     }
1017 
1018     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
1019     if (v->data == NULL) {
1020         return NGX_ERROR;
1021     }
1022 
1023     switch (r->connection->local_sockaddr->sa_family) {
1024 
1025 #if (NGX_HAVE_INET6)
1026     case AF_INET6:
1027         sin6 = (struct sockaddr_in6 *) r->connection->local_sockaddr;
1028         port = ntohs(sin6->sin6_port);
1029         break;
1030 #endif
1031 
1032     default: /* AF_INET */
1033         sin = (struct sockaddr_in *) r->connection->local_sockaddr;
1034         port = ntohs(sin->sin_port);
1035         break;
1036     }
1037 
1038     if (port > 0 && port < 65536) {
1039         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
1040     }
1041 
1042     return NGX_OK;
1043 }
1044 
1045 
1046 static ngx_int_t
1047 ngx_http_variable_scheme(ngx_http_request_t *r,
1048     ngx_http_variable_value_t *v, uintptr_t data)
1049 {
1050 #if (NGX_HTTP_SSL)
1051 
1052     if (r->connection->ssl) {
1053         v->len = sizeof("https") - 1;
1054         v->valid = 1;
1055         v->no_cacheable = 0;
1056         v->not_found = 0;
1057         v->data = (u_char *) "https";
1058 
1059         return NGX_OK;
1060     }
1061 
1062 #endif
1063 
1064     v->len = sizeof("http") - 1;
1065     v->valid = 1;
1066     v->no_cacheable = 0;
1067     v->not_found = 0;
1068     v->data = (u_char *) "http";
1069 
1070     return NGX_OK;
1071 }
1072 
1073 
1074 static ngx_int_t
1075 ngx_http_variable_is_args(ngx_http_request_t *r,
1076     ngx_http_variable_value_t *v, uintptr_t data)
1077 {
1078     v->valid = 1;
1079     v->no_cacheable = 0;
1080     v->not_found = 0;
1081 
1082     if (r->args.len == 0) {
1083         v->len = 0;
1084         v->data = NULL;
1085         return NGX_OK;
1086     }
1087 
1088     v->len = 1;
1089     v->data = (u_char *) "?";
1090 
1091     return NGX_OK;
1092 }
1093 
1094 
1095 static ngx_int_t
1096 ngx_http_variable_document_root(ngx_http_request_t *r,
1097     ngx_http_variable_value_t *v, uintptr_t data)
1098 {
1099     ngx_str_t                  path;
1100     ngx_http_core_loc_conf_t  *clcf;
1101 
1102     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1103 
1104     if (clcf->root_lengths == NULL) {
1105         v->len = clcf->root.len;
1106         v->valid = 1;
1107         v->no_cacheable = 0;
1108         v->not_found = 0;
1109         v->data = clcf->root.data;
1110 
1111     } else {
1112         if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 0,
1113                                 clcf->root_values->elts)
1114             == NULL)
1115         {
1116             return NGX_ERROR;
1117         }
1118 
1119         if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
1120             return NGX_ERROR;
1121         }
1122 
1123         v->len = path.len;
1124         v->valid = 1;
1125         v->no_cacheable = 0;
1126         v->not_found = 0;
1127         v->data = path.data;
1128     }
1129 
1130     return NGX_OK;
1131 }
1132 
1133 
1134 static ngx_int_t
1135 ngx_http_variable_realpath_root(ngx_http_request_t *r,
1136     ngx_http_variable_value_t *v, uintptr_t data)
1137 {
1138     size_t                     len;
1139     ngx_str_t                  path;
1140     ngx_http_core_loc_conf_t  *clcf;
1141     u_char                     real[NGX_MAX_PATH];
1142 
1143     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1144 
1145     if (clcf->root_lengths == NULL) {
1146         path = clcf->root;
1147 
1148     } else {
1149         if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 1,
1150                                 clcf->root_values->elts)
1151             == NULL)
1152         {
1153             return NGX_ERROR;
1154         }
1155 
1156         path.data[path.len - 1] = '\0';
1157 
1158         if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
1159             return NGX_ERROR;
1160         }
1161     }
1162 
1163     if (ngx_realpath(path.data, real) == NULL) {
1164         ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
1165                       ngx_realpath_n " \"%s\" failed", path.data);
1166         return NGX_ERROR;
1167     }
1168 
1169     len = ngx_strlen(real);
1170 
1171     v->data = ngx_pnalloc(r->pool, len);
1172     if (v->data == NULL) {
1173         return NGX_ERROR;
1174     }
1175 
1176     v->len = len;
1177     v->valid = 1;
1178     v->no_cacheable = 0;
1179     v->not_found = 0;
1180 
1181     ngx_memcpy(v->data, real, len);
1182 
1183     return NGX_OK;
1184 }
1185 
1186 
1187 static ngx_int_t
1188 ngx_http_variable_request_filename(ngx_http_request_t *r,
1189     ngx_http_variable_value_t *v, uintptr_t data)
1190 {
1191     size_t     root;
1192     ngx_str_t  path;
1193 
1194     if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
1195         return NGX_ERROR;
1196     }
1197 
1198     /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */
1199 
1200     v->len = path.len - 1;
1201     v->valid = 1;
1202     v->no_cacheable = 0;
1203     v->not_found = 0;
1204     v->data = path.data;
1205 
1206     return NGX_OK;
1207 }
1208 
1209 
1210 static ngx_int_t
1211 ngx_http_variable_server_name(ngx_http_request_t *r,
1212     ngx_http_variable_value_t *v, uintptr_t data)
1213 {
1214     ngx_http_core_srv_conf_t  *cscf;
1215 
1216     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1217 
1218     v->len = cscf->server_name.len;
1219     v->valid = 1;
1220     v->no_cacheable = 0;
1221     v->not_found = 0;
1222     v->data = cscf->server_name.data;
1223 
1224     return NGX_OK;
1225 }
1226 
1227 
1228 static ngx_int_t
1229 ngx_http_variable_request_method(ngx_http_request_t *r,
1230     ngx_http_variable_value_t *v, uintptr_t data)
1231 {
1232     if (r->main->method_name.data) {
1233         v->len = r->main->method_name.len;
1234         v->valid = 1;
1235         v->no_cacheable = 0;
1236         v->not_found = 0;
1237         v->data = r->main->method_name.data;
1238 
1239     } else {
1240         v->not_found = 1;
1241     }
1242 
1243     return NGX_OK;
1244 }
1245 
1246 
1247 static ngx_int_t
1248 ngx_http_variable_remote_user(ngx_http_request_t *r,
1249     ngx_http_variable_value_t *v, uintptr_t data)
1250 {
1251     ngx_int_t  rc;
1252 
1253     rc = ngx_http_auth_basic_user(r);
1254 
1255     if (rc == NGX_DECLINED) {
1256         v->not_found = 1;
1257         return NGX_OK;
1258     }
1259 
1260     if (rc == NGX_ERROR) {
1261         return NGX_ERROR;
1262     }
1263 
1264     v->len = r->headers_in.user.len;
1265     v->valid = 1;
1266     v->no_cacheable = 0;
1267     v->not_found = 0;
1268     v->data = r->headers_in.user.data;
1269 
1270     return NGX_OK;
1271 }
1272 
1273 
1274 static ngx_int_t
1275 ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
1276     ngx_http_variable_value_t *v, uintptr_t data)
1277 {
1278     off_t    sent;
1279     u_char  *p;
1280 
1281     sent = r->connection->sent - r->header_size;
1282 
1283     if (sent < 0) {
1284         sent = 0;
1285     }
1286 
1287     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
1288     if (p == NULL) {
1289         return NGX_ERROR;
1290     }
1291 
1292     v->len = ngx_sprintf(p, "%O", sent) - p;
1293     v->valid = 1;
1294     v->no_cacheable = 0;
1295     v->not_found = 0;
1296     v->data = p;
1297 
1298     return NGX_OK;
1299 }
1300 
1301 
1302 static ngx_int_t
1303 ngx_http_variable_sent_content_type(ngx_http_request_t *r,
1304     ngx_http_variable_value_t *v, uintptr_t data)
1305 {
1306     if (r->headers_out.content_type.len) {
1307         v->len = r->headers_out.content_type.len;
1308         v->valid = 1;
1309         v->no_cacheable = 0;
1310         v->not_found = 0;
1311         v->data = r->headers_out.content_type.data;
1312 
1313     } else {
1314         v->not_found = 1;
1315     }
1316 
1317     return NGX_OK;
1318 }
1319 
1320 
1321 static ngx_int_t
1322 ngx_http_variable_sent_content_length(ngx_http_request_t *r,
1323     ngx_http_variable_value_t *v, uintptr_t data)
1324 {
1325     u_char  *p;
1326 
1327     if (r->headers_out.content_length) {
1328         v->len = r->headers_out.content_length->value.len;
1329         v->valid = 1;
1330         v->no_cacheable = 0;
1331         v->not_found = 0;
1332         v->data = r->headers_out.content_length->value.data;
1333 
1334         return NGX_OK;
1335     }
1336 
1337     if (r->headers_out.content_length_n >= 0) {
1338         p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
1339         if (p == NULL) {
1340             return NGX_ERROR;
1341         }
1342 
1343         v->len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) - p;
1344         v->valid = 1;
1345         v->no_cacheable = 0;
1346         v->not_found = 0;
1347         v->data = p;
1348 
1349         return NGX_OK;
1350     }
1351 
1352     v->not_found = 1;
1353 
1354     return NGX_OK;
1355 }
1356 
1357 
1358 static ngx_int_t
1359 ngx_http_variable_sent_location(ngx_http_request_t *r,
1360     ngx_http_variable_value_t *v, uintptr_t data)
1361 {
1362     ngx_str_t  name;
1363 
1364     if (r->headers_out.location) {
1365         v->len = r->headers_out.location->value.len;
1366         v->valid = 1;
1367         v->no_cacheable = 0;
1368         v->not_found = 0;
1369         v->data = r->headers_out.location->value.data;
1370 
1371         return NGX_OK;
1372     }
1373 
1374     name.len = sizeof("sent_http_location") - 1;
1375     name.data = (u_char *) "sent_http_location";
1376 
1377     return ngx_http_variable_unknown_header(v, &name,
1378                                             &r->headers_out.headers.part,
1379                                             sizeof("sent_http_") - 1);
1380 }
1381 
1382 
1383 static ngx_int_t
1384 ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
1385     ngx_http_variable_value_t *v, uintptr_t data)
1386 {
1387     u_char  *p;
1388 
1389     if (r->headers_out.last_modified) {
1390         v->len = r->headers_out.last_modified->value.len;
1391         v->valid = 1;
1392         v->no_cacheable = 0;
1393         v->not_found = 0;
1394         v->data = r->headers_out.last_modified->value.data;
1395 
1396         return NGX_OK;
1397     }
1398 
1399     if (r->headers_out.last_modified_time >= 0) {
1400         p = ngx_pnalloc(r->pool,
1401                    sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT") - 1);
1402         if (p == NULL) {
1403             return NGX_ERROR;
1404         }
1405 
1406         v->len = ngx_http_time(p, r->headers_out.last_modified_time) - p;
1407         v->valid = 1;
1408         v->no_cacheable = 0;
1409         v->not_found = 0;
1410         v->data = p;
1411 
1412         return NGX_OK;
1413     }
1414 
1415     v->not_found = 1;
1416 
1417     return NGX_OK;
1418 }
1419 
1420 
1421 static ngx_int_t
1422 ngx_http_variable_sent_connection(ngx_http_request_t *r,
1423     ngx_http_variable_value_t *v, uintptr_t data)
1424 {
1425     size_t   len;
1426     char    *p;
1427 
1428     if (r->keepalive) {
1429         len = sizeof("keep-alive") - 1;
1430         p = "keep-alive";
1431 
1432     } else {
1433         len = sizeof("close") - 1;
1434         p = "close";
1435     }
1436 
1437     v->len = len;
1438     v->valid = 1;
1439     v->no_cacheable = 0;
1440     v->not_found = 0;
1441     v->data = (u_char *) p;
1442 
1443     return NGX_OK;
1444 }
1445 
1446 
1447 static ngx_int_t
1448 ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
1449     ngx_http_variable_value_t *v, uintptr_t data)
1450 {
1451     u_char                    *p;
1452     ngx_http_core_loc_conf_t  *clcf;
1453 
1454     if (r->keepalive) {
1455         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1456 
1457         if (clcf->keepalive_header) {
1458 
1459             p = ngx_pnalloc(r->pool, sizeof("timeout=") - 1 + NGX_TIME_T_LEN);
1460             if (p == NULL) {
1461                 return NGX_ERROR;
1462             }
1463 
1464             v->len = ngx_sprintf(p, "timeout=%T", clcf->keepalive_header) - p;
1465             v->valid = 1;
1466             v->no_cacheable = 0;
1467             v->not_found = 0;
1468             v->data = p;
1469 
1470             return NGX_OK;
1471         }
1472     }
1473 
1474     v->not_found = 1;
1475 
1476     return NGX_OK;
1477 }
1478 
1479 
1480 static ngx_int_t
1481 ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
1482     ngx_http_variable_value_t *v, uintptr_t data)
1483 {
1484     if (r->chunked) {
1485         v->len = sizeof("chunked") - 1;
1486         v->valid = 1;
1487         v->no_cacheable = 0;
1488         v->not_found = 0;
1489         v->data = (u_char *) "chunked";
1490 
1491     } else {
1492         v->not_found = 1;
1493     }
1494 
1495     return NGX_OK;
1496 }
1497 
1498 
1499 static ngx_int_t
1500 ngx_http_variable_request_completion(ngx_http_request_t *r,
1501     ngx_http_variable_value_t *v, uintptr_t data)
1502 {
1503     if (r->request_complete) {
1504         v->len = 2;
1505         v->valid = 1;
1506         v->no_cacheable = 0;
1507         v->not_found = 0;
1508         v->data = (u_char *) "OK";
1509 
1510         return NGX_OK;
1511     }
1512 
1513     v->len = 0;
1514     v->valid = 1;
1515     v->no_cacheable = 0;
1516     v->not_found = 0;
1517     v->data = (u_char *) "";
1518 
1519     return NGX_OK;
1520 }
1521 
1522 
1523 static ngx_int_t
1524 ngx_http_variable_request_body(ngx_http_request_t *r,
1525     ngx_http_variable_value_t *v, uintptr_t data)
1526 {
1527     u_char       *p;
1528     size_t        len;
1529     ngx_buf_t    *buf, *next;
1530     ngx_chain_t  *cl;
1531 
1532     if (r->request_body == NULL
1533         || r->request_body->bufs == NULL
1534         || r->request_body->temp_file)
1535     {
1536         v->not_found = 1;
1537 
1538         return NGX_OK;
1539     }
1540 
1541     cl = r->request_body->bufs;
1542     buf = cl->buf;
1543 
1544     if (cl->next == NULL) {
1545         v->len = buf->last - buf->pos;
1546         v->valid = 1;
1547         v->no_cacheable = 0;
1548         v->not_found = 0;
1549         v->data = buf->pos;
1550 
1551         return NGX_OK;
1552     }
1553 
1554     next = cl->next->buf;
1555     len = (buf->last - buf->pos) + (next->last - next->pos);
1556 
1557     p = ngx_pnalloc(r->pool, len);
1558     if (p == NULL) {
1559         return NGX_ERROR;
1560     }
1561 
1562     v->data = p;
1563 
1564     p = ngx_cpymem(p, buf->pos, buf->last - buf->pos);
1565     ngx_memcpy(p, next->pos, next->last - next->pos);
1566 
1567     v->len = len;
1568     v->valid = 1;
1569     v->no_cacheable = 0;
1570     v->not_found = 0;
1571 
1572     return NGX_OK;
1573 }
1574 
1575 
1576 static ngx_int_t
1577 ngx_http_variable_request_body_file(ngx_http_request_t *r,
1578     ngx_http_variable_value_t *v, uintptr_t data)
1579 {
1580     if (r->request_body == NULL || r->request_body->temp_file == NULL) {
1581         v->not_found = 1;
1582 
1583         return NGX_OK;
1584     }
1585 
1586     v->len = r->request_body->temp_file->file.name.len;
1587     v->valid = 1;
1588     v->no_cacheable = 0;
1589     v->not_found = 0;
1590     v->data = r->request_body->temp_file->file.name.data;
1591 
1592     return NGX_OK;
1593 }
1594 
1595 
1596 static ngx_int_t
1597 ngx_http_variable_nginx_version(ngx_http_request_t *r,
1598     ngx_http_variable_value_t *v, uintptr_t data)
1599 {
1600     v->len = sizeof(NGINX_VERSION) - 1;
1601     v->valid = 1;
1602     v->no_cacheable = 0;
1603     v->not_found = 0;
1604     v->data = (u_char *) NGINX_VERSION;
1605 
1606     return NGX_OK;
1607 }
1608 
1609 
1610 static ngx_int_t
1611 ngx_http_variable_hostname(ngx_http_request_t *r,
1612     ngx_http_variable_value_t *v, uintptr_t data)
1613 {
1614     v->len = ngx_cycle->hostname.len;
1615     v->valid = 1;
1616     v->no_cacheable = 0;
1617     v->not_found = 0;
1618     v->data = ngx_cycle->hostname.data;
1619 
1620     return NGX_OK;
1621 }
1622 
1623 
1624 static ngx_int_t
1625 ngx_http_variable_pid(ngx_http_request_t *r,
1626     ngx_http_variable_value_t *v, uintptr_t data)
1627 {
1628     u_char  *p;
1629 
1630     p = ngx_pnalloc(r->pool, NGX_INT64_LEN);
1631     if (p == NULL) {
1632         return NGX_ERROR;
1633     }
1634 
1635     v->len = ngx_sprintf(p, "%P", ngx_pid) - p;
1636     v->valid = 1;
1637     v->no_cacheable = 0;
1638     v->not_found = 0;
1639     v->data = p;
1640 
1641     return NGX_OK;
1642 }
1643 
1644 
1645 ngx_int_t
1646 ngx_http_variables_add_core_vars(ngx_conf_t *cf)
1647 {
1648     ngx_int_t                   rc;
1649     ngx_http_variable_t        *v;
1650     ngx_http_core_main_conf_t  *cmcf;
1651 
1652     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1653 
1654     cmcf->variables_keys = ngx_pcalloc(cf->temp_pool,
1655                                        sizeof(ngx_hash_keys_arrays_t));
1656     if (cmcf->variables_keys == NULL) {
1657         return NGX_ERROR;
1658     }
1659 
1660     cmcf->variables_keys->pool = cf->pool;
1661     cmcf->variables_keys->temp_pool = cf->pool;
1662 
1663     if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL)
1664         != NGX_OK)
1665     {
1666         return NGX_ERROR;
1667     }
1668 
1669     for (v = ngx_http_core_variables; v->name.len; v++) {
1670         rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v,
1671                               NGX_HASH_READONLY_KEY);
1672 
1673         if (rc == NGX_OK) {
1674             continue;
1675         }
1676 
1677         if (rc == NGX_BUSY) {
1678             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1679                                "conflicting variable name \"%V\"", &v->name);
1680         }
1681 
1682         return NGX_ERROR;
1683     }
1684 
1685     return NGX_OK;
1686 }
1687 
1688 
1689 ngx_int_t
1690 ngx_http_variables_init_vars(ngx_conf_t *cf)
1691 {
1692     ngx_uint_t                  i, n;
1693     ngx_hash_key_t             *key;
1694     ngx_hash_init_t             hash;
1695     ngx_http_variable_t        *v, *av;
1696     ngx_http_core_main_conf_t  *cmcf;
1697 
1698     /* set the handlers for the indexed http variables */
1699 
1700     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1701 
1702     v = cmcf->variables.elts;
1703     key = cmcf->variables_keys->keys.elts;
1704 
1705     for (i = 0; i < cmcf->variables.nelts; i++) {
1706 
1707         for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {
1708 
1709             av = key[n].value;
1710 
1711             if (av->get_handler
1712                 && v[i].name.len == key[n].key.len
1713                 && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len)
1714                    == 0)
1715             {
1716                 v[i].get_handler = av->get_handler;
1717                 v[i].data = av->data;
1718 
1719                 av->flags |= NGX_HTTP_VAR_INDEXED;
1720                 v[i].flags = av->flags;
1721 
1722                 av->index = i;
1723 
1724                 goto next;
1725             }
1726         }
1727 
1728         if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) {
1729             v[i].get_handler = ngx_http_variable_unknown_header_in;
1730             v[i].data = (uintptr_t) &v[i].name;
1731 
1732             continue;
1733         }
1734 
1735         if (ngx_strncmp(v[i].name.data, "sent_http_", 10) == 0) {
1736             v[i].get_handler = ngx_http_variable_unknown_header_out;
1737             v[i].data = (uintptr_t) &v[i].name;
1738 
1739             continue;
1740         }
1741 
1742         if (ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0) {
1743             v[i].get_handler = ngx_http_upstream_header_variable;
1744             v[i].data = (uintptr_t) &v[i].name;
1745             v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;
1746 
1747             continue;
1748         }
1749 
1750         if (ngx_strncmp(v[i].name.data, "cookie_", 7) == 0) {
1751             v[i].get_handler = ngx_http_variable_cookie;
1752             v[i].data = (uintptr_t) &v[i].name;
1753 
1754             continue;
1755         }
1756 
1757         if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) {
1758             v[i].get_handler = ngx_http_variable_argument;
1759             v[i].data = (uintptr_t) &v[i].name;
1760 
1761             continue;
1762         }
1763 
1764         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
1765                       "unknown \"%V\" variable", &v[i].name);
1766 
1767         return NGX_ERROR;
1768 
1769     next:
1770         continue;
1771     }
1772 
1773 
1774     for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {
1775         av = key[n].value;
1776 
1777         if (av->flags & NGX_HTTP_VAR_NOHASH) {
1778             key[n].key.data = NULL;
1779         }
1780     }
1781 
1782 
1783     hash.hash = &cmcf->variables_hash;
1784     hash.key = ngx_hash_key;
1785     hash.max_size = cmcf->variables_hash_max_size;
1786     hash.bucket_size = cmcf->variables_hash_bucket_size;
1787     hash.name = "variables_hash";
1788     hash.pool = cf->pool;
1789     hash.temp_pool = NULL;
1790 
1791     if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts,
1792                       cmcf->variables_keys->keys.nelts)
1793         != NGX_OK)
1794     {
1795         return NGX_ERROR;
1796     }
1797 
1798     cmcf->variables_keys = NULL;
1799 
1800     return NGX_OK;
1801 }
1802 
1803 
1804 void
1805 ngx_http_variable_value_rbtree_insert(ngx_rbtree_node_t *temp,
1806     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
1807 {
1808     ngx_rbtree_node_t               **p;
1809     ngx_http_variable_value_node_t   *vvn, *vvt;
1810 
1811     for ( ;; ) {
1812 
1813         vvn = (ngx_http_variable_value_node_t *) node;
1814         vvt = (ngx_http_variable_value_node_t *) temp;
1815 
1816         if (node->key != temp->key) {
1817 
1818             p = (node->key < temp->key) ? &temp->left : &temp->right;
1819 
1820         } else if (vvn->len != vvt->len) {
1821 
1822             p = (vvn->len < vvt->len) ? &temp->left : &temp->right;
1823 
1824         } else {
1825             p = (ngx_memcmp(vvn->value->data, vvt->value->data, vvn->len) < 0)
1826                  ? &temp->left : &temp->right;
1827         }
1828 
1829         if (*p == sentinel) {
1830             break;
1831         }
1832 
1833         temp = *p;
1834     }
1835 
1836     *p = node;
1837     node->parent = temp;
1838     node->left = sentinel;
1839     node->right = sentinel;
1840     ngx_rbt_red(node);
1841 }
1842 
1843 
1844 ngx_http_variable_value_t *
1845 ngx_http_variable_value_lookup(ngx_rbtree_t *rbtree, ngx_str_t *val,
1846     uint32_t hash)
1847 {
1848     ngx_int_t                        rc;
1849     ngx_rbtree_node_t               *node, *sentinel;
1850     ngx_http_variable_value_node_t  *vvn;
1851 
1852     node = rbtree->root;
1853     sentinel = rbtree->sentinel;
1854 
1855     while (node != sentinel) {
1856 
1857         vvn = (ngx_http_variable_value_node_t *) node;
1858 
1859         if (hash != node->key) {
1860             node = (hash < node->key) ? node->left : node->right;
1861             continue;
1862         }
1863 
1864         if (val->len != vvn->len) {
1865             node = (val->len < vvn->len) ? node->left : node->right;
1866             continue;
1867         }
1868 
1869         rc = ngx_memcmp(val->data, vvn->value->data, val->len);
1870 
1871         if (rc < 0) {
1872             node = node->left;
1873             continue;
1874         }
1875 
1876         if (rc > 0) {
1877             node = node->right;
1878             continue;
1879         }
1880 
1881         return vvn->value;
1882     }
1883 
1884     return NULL;
1885 }
1886 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.