src/http/ngx_http_variables.c - nginx-1.7.10

Global variables defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_http.h>
  8. #include <nginx.h>


  9. static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r,
  10.     ngx_http_variable_value_t *v, uintptr_t data);
  11. #if 0
  12. static void ngx_http_variable_request_set(ngx_http_request_t *r,
  13.     ngx_http_variable_value_t *v, uintptr_t data);
  14. #endif
  15. static ngx_int_t ngx_http_variable_request_get_size(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_cookies(ngx_http_request_t *r,
  22.     ngx_http_variable_value_t *v, uintptr_t data);
  23. static ngx_int_t ngx_http_variable_headers(ngx_http_request_t *r,
  24.     ngx_http_variable_value_t *v, uintptr_t data);
  25. static ngx_int_t ngx_http_variable_headers_internal(ngx_http_request_t *r,
  26.     ngx_http_variable_value_t *v, uintptr_t data, u_char sep);

  27. static ngx_int_t ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
  28.     ngx_http_variable_value_t *v, uintptr_t data);
  29. static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
  30.     ngx_http_variable_value_t *v, uintptr_t data);
  31. static ngx_int_t ngx_http_variable_request_line(ngx_http_request_t *r,
  32.     ngx_http_variable_value_t *v, uintptr_t data);
  33. static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r,
  34.     ngx_http_variable_value_t *v, uintptr_t data);
  35. static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r,
  36.     ngx_http_variable_value_t *v, uintptr_t data);
  37. #if (NGX_HAVE_TCP_INFO)
  38. static ngx_int_t ngx_http_variable_tcpinfo(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_content_length(ngx_http_request_t *r,
  42.     ngx_http_variable_value_t *v, uintptr_t data);
  43. static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r,
  44.     ngx_http_variable_value_t *v, uintptr_t data);
  45. static ngx_int_t ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
  46.     ngx_http_variable_value_t *v, uintptr_t data);
  47. static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r,
  48.     ngx_http_variable_value_t *v, uintptr_t data);
  49. static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r,
  50.     ngx_http_variable_value_t *v, uintptr_t data);
  51. static ngx_int_t ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
  52.     ngx_http_variable_value_t *v, uintptr_t data);
  53. static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r,
  54.     ngx_http_variable_value_t *v, uintptr_t data);
  55. static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
  56.     ngx_http_variable_value_t *v, uintptr_t data);
  57. static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r,
  58.     ngx_http_variable_value_t *v, uintptr_t data);
  59. static ngx_int_t ngx_http_variable_https(ngx_http_request_t *r,
  60.     ngx_http_variable_value_t *v, uintptr_t data);
  61. static void ngx_http_variable_set_args(ngx_http_request_t *r,
  62.     ngx_http_variable_value_t *v, uintptr_t data);
  63. static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r,
  64.     ngx_http_variable_value_t *v, uintptr_t data);
  65. static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r,
  66.     ngx_http_variable_value_t *v, uintptr_t data);
  67. static ngx_int_t ngx_http_variable_realpath_root(ngx_http_request_t *r,
  68.     ngx_http_variable_value_t *v, uintptr_t data);
  69. static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r,
  70.     ngx_http_variable_value_t *v, uintptr_t data);
  71. static ngx_int_t ngx_http_variable_server_name(ngx_http_request_t *r,
  72.     ngx_http_variable_value_t *v, uintptr_t data);
  73. static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r,
  74.     ngx_http_variable_value_t *v, uintptr_t data);
  75. static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r,
  76.     ngx_http_variable_value_t *v, uintptr_t data);
  77. static ngx_int_t ngx_http_variable_bytes_sent(ngx_http_request_t *r,
  78.     ngx_http_variable_value_t *v, uintptr_t data);
  79. static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
  80.     ngx_http_variable_value_t *v, uintptr_t data);
  81. static ngx_int_t ngx_http_variable_pipe(ngx_http_request_t *r,
  82.     ngx_http_variable_value_t *v, uintptr_t data);
  83. static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
  84.     ngx_http_variable_value_t *v, uintptr_t data);
  85. static ngx_int_t ngx_http_variable_request_body(ngx_http_request_t *r,
  86.     ngx_http_variable_value_t *v, uintptr_t data);
  87. static ngx_int_t ngx_http_variable_request_body_file(ngx_http_request_t *r,
  88.     ngx_http_variable_value_t *v, uintptr_t data);
  89. static ngx_int_t ngx_http_variable_request_length(ngx_http_request_t *r,
  90.     ngx_http_variable_value_t *v, uintptr_t data);
  91. static ngx_int_t ngx_http_variable_request_time(ngx_http_request_t *r,
  92.     ngx_http_variable_value_t *v, uintptr_t data);
  93. static ngx_int_t ngx_http_variable_status(ngx_http_request_t *r,
  94.     ngx_http_variable_value_t *v, uintptr_t data);

  95. static ngx_int_t ngx_http_variable_sent_content_type(ngx_http_request_t *r,
  96.     ngx_http_variable_value_t *v, uintptr_t data);
  97. static ngx_int_t ngx_http_variable_sent_content_length(ngx_http_request_t *r,
  98.     ngx_http_variable_value_t *v, uintptr_t data);
  99. static ngx_int_t ngx_http_variable_sent_location(ngx_http_request_t *r,
  100.     ngx_http_variable_value_t *v, uintptr_t data);
  101. static ngx_int_t ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
  102.     ngx_http_variable_value_t *v, uintptr_t data);
  103. static ngx_int_t ngx_http_variable_sent_connection(ngx_http_request_t *r,
  104.     ngx_http_variable_value_t *v, uintptr_t data);
  105. static ngx_int_t ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
  106.     ngx_http_variable_value_t *v, uintptr_t data);
  107. static ngx_int_t ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
  108.     ngx_http_variable_value_t *v, uintptr_t data);

  109. static ngx_int_t ngx_http_variable_connection(ngx_http_request_t *r,
  110.     ngx_http_variable_value_t *v, uintptr_t data);
  111. static ngx_int_t ngx_http_variable_connection_requests(ngx_http_request_t *r,
  112.     ngx_http_variable_value_t *v, uintptr_t data);

  113. static ngx_int_t ngx_http_variable_nginx_version(ngx_http_request_t *r,
  114.     ngx_http_variable_value_t *v, uintptr_t data);
  115. static ngx_int_t ngx_http_variable_hostname(ngx_http_request_t *r,
  116.     ngx_http_variable_value_t *v, uintptr_t data);
  117. static ngx_int_t ngx_http_variable_pid(ngx_http_request_t *r,
  118.     ngx_http_variable_value_t *v, uintptr_t data);
  119. static ngx_int_t ngx_http_variable_msec(ngx_http_request_t *r,
  120.     ngx_http_variable_value_t *v, uintptr_t data);
  121. static ngx_int_t ngx_http_variable_time_iso8601(ngx_http_request_t *r,
  122.     ngx_http_variable_value_t *v, uintptr_t data);
  123. static ngx_int_t ngx_http_variable_time_local(ngx_http_request_t *r,
  124.     ngx_http_variable_value_t *v, uintptr_t data);

  125. /*
  126. * TODO:
  127. *     Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED
  128. *                 REMOTE_HOST (null), REMOTE_IDENT (null),
  129. *                 SERVER_SOFTWARE
  130. *
  131. *     Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner)
  132. */

  133. /*
  134. * the $http_host, $http_user_agent, $http_referer, and $http_via
  135. * variables may be handled by generic
  136. * ngx_http_variable_unknown_header_in(), but for performance reasons
  137. * they are handled using dedicated entries
  138. */

  139. static ngx_http_variable_t  ngx_http_core_variables[] = {

  140.     { ngx_string("http_host"), NULL, ngx_http_variable_header,
  141.       offsetof(ngx_http_request_t, headers_in.host), 0, 0 },

  142.     { ngx_string("http_user_agent"), NULL, ngx_http_variable_header,
  143.       offsetof(ngx_http_request_t, headers_in.user_agent), 0, 0 },

  144.     { ngx_string("http_referer"), NULL, ngx_http_variable_header,
  145.       offsetof(ngx_http_request_t, headers_in.referer), 0, 0 },

  146. #if (NGX_HTTP_GZIP)
  147.     { ngx_string("http_via"), NULL, ngx_http_variable_header,
  148.       offsetof(ngx_http_request_t, headers_in.via), 0, 0 },
  149. #endif

  150. #if (NGX_HTTP_X_FORWARDED_FOR)
  151.     { ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_headers,
  152.       offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 },
  153. #endif

  154.     { ngx_string("http_cookie"), NULL, ngx_http_variable_cookies,
  155.       offsetof(ngx_http_request_t, headers_in.cookies), 0, 0 },

  156.     { ngx_string("content_length"), NULL, ngx_http_variable_content_length,
  157.       0, 0, 0 },

  158.     { ngx_string("content_type"), NULL, ngx_http_variable_header,
  159.       offsetof(ngx_http_request_t, headers_in.content_type), 0, 0 },

  160.     { ngx_string("host"), NULL, ngx_http_variable_host, 0, 0, 0 },

  161.     { ngx_string("binary_remote_addr"), NULL,
  162.       ngx_http_variable_binary_remote_addr, 0, 0, 0 },

  163.     { ngx_string("remote_addr"), NULL, ngx_http_variable_remote_addr, 0, 0, 0 },

  164.     { ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 },

  165.     { ngx_string("proxy_protocol_addr"), NULL,
  166.       ngx_http_variable_proxy_protocol_addr, 0, 0, 0 },

  167.     { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },

  168.     { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 },

  169.     { ngx_string("server_protocol"), NULL, ngx_http_variable_request,
  170.       offsetof(ngx_http_request_t, http_protocol), 0, 0 },

  171.     { ngx_string("scheme"), NULL, ngx_http_variable_scheme, 0, 0, 0 },

  172.     { ngx_string("https"), NULL, ngx_http_variable_https, 0, 0, 0 },

  173.     { ngx_string("request_uri"), NULL, ngx_http_variable_request,
  174.       offsetof(ngx_http_request_t, unparsed_uri), 0, 0 },

  175.     { ngx_string("uri"), NULL, ngx_http_variable_request,
  176.       offsetof(ngx_http_request_t, uri),
  177.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  178.     { ngx_string("document_uri"), NULL, ngx_http_variable_request,
  179.       offsetof(ngx_http_request_t, uri),
  180.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  181.     { ngx_string("request"), NULL, ngx_http_variable_request_line, 0, 0, 0 },

  182.     { ngx_string("document_root"), NULL,
  183.       ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  184.     { ngx_string("realpath_root"), NULL,
  185.       ngx_http_variable_realpath_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  186.     { ngx_string("query_string"), NULL, ngx_http_variable_request,
  187.       offsetof(ngx_http_request_t, args),
  188.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  189.     { ngx_string("args"),
  190.       ngx_http_variable_set_args,
  191.       ngx_http_variable_request,
  192.       offsetof(ngx_http_request_t, args),
  193.       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },

  194.     { ngx_string("is_args"), NULL, ngx_http_variable_is_args,
  195.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  196.     { ngx_string("request_filename"), NULL,
  197.       ngx_http_variable_request_filename, 0,
  198.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  199.     { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 },

  200.     { ngx_string("request_method"), NULL,
  201.       ngx_http_variable_request_method, 0,
  202.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  203.     { ngx_string("remote_user"), NULL, ngx_http_variable_remote_user, 0, 0, 0 },

  204.     { ngx_string("bytes_sent"), NULL, ngx_http_variable_bytes_sent,
  205.       0, 0, 0 },

  206.     { ngx_string("body_bytes_sent"), NULL, ngx_http_variable_body_bytes_sent,
  207.       0, 0, 0 },

  208.     { ngx_string("pipe"), NULL, ngx_http_variable_pipe,
  209.       0, 0, 0 },

  210.     { ngx_string("request_completion"), NULL,
  211.       ngx_http_variable_request_completion,
  212.       0, 0, 0 },

  213.     { ngx_string("request_body"), NULL,
  214.       ngx_http_variable_request_body,
  215.       0, 0, 0 },

  216.     { ngx_string("request_body_file"), NULL,
  217.       ngx_http_variable_request_body_file,
  218.       0, 0, 0 },

  219.     { ngx_string("request_length"), NULL, ngx_http_variable_request_length,
  220.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  221.     { ngx_string("request_time"), NULL, ngx_http_variable_request_time,
  222.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  223.     { ngx_string("status"), NULL,
  224.       ngx_http_variable_status, 0,
  225.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  226.     { ngx_string("sent_http_content_type"), NULL,
  227.       ngx_http_variable_sent_content_type, 0, 0, 0 },

  228.     { ngx_string("sent_http_content_length"), NULL,
  229.       ngx_http_variable_sent_content_length, 0, 0, 0 },

  230.     { ngx_string("sent_http_location"), NULL,
  231.       ngx_http_variable_sent_location, 0, 0, 0 },

  232.     { ngx_string("sent_http_last_modified"), NULL,
  233.       ngx_http_variable_sent_last_modified, 0, 0, 0 },

  234.     { ngx_string("sent_http_connection"), NULL,
  235.       ngx_http_variable_sent_connection, 0, 0, 0 },

  236.     { ngx_string("sent_http_keep_alive"), NULL,
  237.       ngx_http_variable_sent_keep_alive, 0, 0, 0 },

  238.     { ngx_string("sent_http_transfer_encoding"), NULL,
  239.       ngx_http_variable_sent_transfer_encoding, 0, 0, 0 },

  240.     { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers,
  241.       offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 },

  242.     { ngx_string("limit_rate"), ngx_http_variable_request_set_size,
  243.       ngx_http_variable_request_get_size,
  244.       offsetof(ngx_http_request_t, limit_rate),
  245.       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },

  246.     { ngx_string("connection"), NULL,
  247.       ngx_http_variable_connection, 0, 0, 0 },

  248.     { ngx_string("connection_requests"), NULL,
  249.       ngx_http_variable_connection_requests, 0, 0, 0 },

  250.     { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version,
  251.       0, 0, 0 },

  252.     { ngx_string("hostname"), NULL, ngx_http_variable_hostname,
  253.       0, 0, 0 },

  254.     { ngx_string("pid"), NULL, ngx_http_variable_pid,
  255.       0, 0, 0 },

  256.     { ngx_string("msec"), NULL, ngx_http_variable_msec,
  257.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  258.     { ngx_string("time_iso8601"), NULL, ngx_http_variable_time_iso8601,
  259.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  260.     { ngx_string("time_local"), NULL, ngx_http_variable_time_local,
  261.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  262. #if (NGX_HAVE_TCP_INFO)
  263.     { ngx_string("tcpinfo_rtt"), NULL, ngx_http_variable_tcpinfo,
  264.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  265.     { ngx_string("tcpinfo_rttvar"), NULL, ngx_http_variable_tcpinfo,
  266.       1, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  267.     { ngx_string("tcpinfo_snd_cwnd"), NULL, ngx_http_variable_tcpinfo,
  268.       2, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  269.     { ngx_string("tcpinfo_rcv_space"), NULL, ngx_http_variable_tcpinfo,
  270.       3, NGX_HTTP_VAR_NOCACHEABLE, 0 },
  271. #endif

  272.     { ngx_null_string, NULL, NULL, 0, 0, 0 }
  273. };


  274. ngx_http_variable_value_t  ngx_http_variable_null_value =
  275.     ngx_http_variable("");
  276. ngx_http_variable_value_t  ngx_http_variable_true_value =
  277.     ngx_http_variable("1");


  278. ngx_http_variable_t *
  279. ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
  280. {
  281.     ngx_int_t                   rc;
  282.     ngx_uint_t                  i;
  283.     ngx_hash_key_t             *key;
  284.     ngx_http_variable_t        *v;
  285.     ngx_http_core_main_conf_t  *cmcf;

  286.     if (name->len == 0) {
  287.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  288.                            "invalid variable name \"$\"");
  289.         return NULL;
  290.     }

  291.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

  292.     key = cmcf->variables_keys->keys.elts;
  293.     for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) {
  294.         if (name->len != key[i].key.len
  295.             || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0)
  296.         {
  297.             continue;
  298.         }

  299.         v = key[i].value;

  300.         if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
  301.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  302.                                "the duplicate \"%V\" variable", name);
  303.             return NULL;
  304.         }

  305.         return v;
  306.     }

  307.     v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));
  308.     if (v == NULL) {
  309.         return NULL;
  310.     }

  311.     v->name.len = name->len;
  312.     v->name.data = ngx_pnalloc(cf->pool, name->len);
  313.     if (v->name.data == NULL) {
  314.         return NULL;
  315.     }

  316.     ngx_strlow(v->name.data, name->data, name->len);

  317.     v->set_handler = NULL;
  318.     v->get_handler = NULL;
  319.     v->data = 0;
  320.     v->flags = flags;
  321.     v->index = 0;

  322.     rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0);

  323.     if (rc == NGX_ERROR) {
  324.         return NULL;
  325.     }

  326.     if (rc == NGX_BUSY) {
  327.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  328.                            "conflicting variable name \"%V\"", name);
  329.         return NULL;
  330.     }

  331.     return v;
  332. }


  333. ngx_int_t
  334. ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name)
  335. {
  336.     ngx_uint_t                  i;
  337.     ngx_http_variable_t        *v;
  338.     ngx_http_core_main_conf_t  *cmcf;

  339.     if (name->len == 0) {
  340.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  341.                            "invalid variable name \"$\"");
  342.         return NGX_ERROR;
  343.     }

  344.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

  345.     v = cmcf->variables.elts;

  346.     if (v == NULL) {
  347.         if (ngx_array_init(&cmcf->variables, cf->pool, 4,
  348.                            sizeof(ngx_http_variable_t))
  349.             != NGX_OK)
  350.         {
  351.             return NGX_ERROR;
  352.         }

  353.     } else {
  354.         for (i = 0; i < cmcf->variables.nelts; i++) {
  355.             if (name->len != v[i].name.len
  356.                 || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0)
  357.             {
  358.                 continue;
  359.             }

  360.             return i;
  361.         }
  362.     }

  363.     v = ngx_array_push(&cmcf->variables);
  364.     if (v == NULL) {
  365.         return NGX_ERROR;
  366.     }

  367.     v->name.len = name->len;
  368.     v->name.data = ngx_pnalloc(cf->pool, name->len);
  369.     if (v->name.data == NULL) {
  370.         return NGX_ERROR;
  371.     }

  372.     ngx_strlow(v->name.data, name->data, name->len);

  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.     return v->index;
  379. }


  380. ngx_http_variable_value_t *
  381. ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
  382. {
  383.     ngx_http_variable_t        *v;
  384.     ngx_http_core_main_conf_t  *cmcf;

  385.     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

  386.     if (cmcf->variables.nelts <= index) {
  387.         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  388.                       "unknown variable index: %ui", index);
  389.         return NULL;
  390.     }

  391.     if (r->variables[index].not_found || r->variables[index].valid) {
  392.         return &r->variables[index];
  393.     }

  394.     v = cmcf->variables.elts;

  395.     if (v[index].get_handler(r, &r->variables[index], v[index].data)
  396.         == NGX_OK)
  397.     {
  398.         if (v[index].flags & NGX_HTTP_VAR_NOCACHEABLE) {
  399.             r->variables[index].no_cacheable = 1;
  400.         }

  401.         return &r->variables[index];
  402.     }

  403.     r->variables[index].valid = 0;
  404.     r->variables[index].not_found = 1;

  405.     return NULL;
  406. }


  407. ngx_http_variable_value_t *
  408. ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index)
  409. {
  410.     ngx_http_variable_value_t  *v;

  411.     v = &r->variables[index];

  412.     if (v->valid || v->not_found) {
  413.         if (!v->no_cacheable) {
  414.             return v;
  415.         }

  416.         v->valid = 0;
  417.         v->not_found = 0;
  418.     }

  419.     return ngx_http_get_indexed_variable(r, index);
  420. }


  421. ngx_http_variable_value_t *
  422. ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
  423. {
  424.     ngx_http_variable_t        *v;
  425.     ngx_http_variable_value_t  *vv;
  426.     ngx_http_core_main_conf_t  *cmcf;

  427.     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

  428.     v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len);

  429.     if (v) {
  430.         if (v->flags & NGX_HTTP_VAR_INDEXED) {
  431.             return ngx_http_get_flushed_variable(r, v->index);

  432.         } else {

  433.             vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));

  434.             if (vv && v->get_handler(r, vv, v->data) == NGX_OK) {
  435.                 return vv;
  436.             }

  437.             return NULL;
  438.         }
  439.     }

  440.     vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
  441.     if (vv == NULL) {
  442.         return NULL;
  443.     }

  444.     if (ngx_strncmp(name->data, "http_", 5) == 0) {

  445.         if (ngx_http_variable_unknown_header_in(r, vv, (uintptr_t) name)
  446.             == NGX_OK)
  447.         {
  448.             return vv;
  449.         }

  450.         return NULL;
  451.     }

  452.     if (ngx_strncmp(name->data, "sent_http_", 10) == 0) {

  453.         if (ngx_http_variable_unknown_header_out(r, vv, (uintptr_t) name)
  454.             == NGX_OK)
  455.         {
  456.             return vv;
  457.         }

  458.         return NULL;
  459.     }

  460.     if (ngx_strncmp(name->data, "upstream_http_", 14) == 0) {

  461.         if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name)
  462.             == NGX_OK)
  463.         {
  464.             return vv;
  465.         }

  466.         return NULL;
  467.     }

  468.     if (ngx_strncmp(name->data, "cookie_", 7) == 0) {

  469.         if (ngx_http_variable_cookie(r, vv, (uintptr_t) name) == NGX_OK) {
  470.             return vv;
  471.         }

  472.         return NULL;
  473.     }

  474.     if (ngx_strncmp(name->data, "upstream_cookie_", 16) == 0) {

  475.         if (ngx_http_upstream_cookie_variable(r, vv, (uintptr_t) name)
  476.             == NGX_OK)
  477.         {
  478.             return vv;
  479.         }

  480.         return NULL;
  481.     }

  482.     if (ngx_strncmp(name->data, "arg_", 4) == 0) {

  483.         if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) {
  484.             return vv;
  485.         }

  486.         return NULL;
  487.     }

  488.     vv->not_found = 1;

  489.     return vv;
  490. }


  491. static ngx_int_t
  492. ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  493.     uintptr_t data)
  494. {
  495.     ngx_str_t  *s;

  496.     s = (ngx_str_t *) ((char *) r + data);

  497.     if (s->data) {
  498.         v->len = s->len;
  499.         v->valid = 1;
  500.         v->no_cacheable = 0;
  501.         v->not_found = 0;
  502.         v->data = s->data;

  503.     } else {
  504.         v->not_found = 1;
  505.     }

  506.     return NGX_OK;
  507. }


  508. #if 0

  509. static void
  510. ngx_http_variable_request_set(ngx_http_request_t *r,
  511.     ngx_http_variable_value_t *v, uintptr_t data)
  512. {
  513.     ngx_str_t  *s;

  514.     s = (ngx_str_t *) ((char *) r + data);

  515.     s->len = v->len;
  516.     s->data = v->data;
  517. }

  518. #endif


  519. static ngx_int_t
  520. ngx_http_variable_request_get_size(ngx_http_request_t *r,
  521.     ngx_http_variable_value_t *v, uintptr_t data)
  522. {
  523.     size_t  *sp;

  524.     sp = (size_t *) ((char *) r + data);

  525.     v->data = ngx_pnalloc(r->pool, NGX_SIZE_T_LEN);
  526.     if (v->data == NULL) {
  527.         return NGX_ERROR;
  528.     }

  529.     v->len = ngx_sprintf(v->data, "%uz", *sp) - v->data;
  530.     v->valid = 1;
  531.     v->no_cacheable = 0;
  532.     v->not_found = 0;

  533.     return NGX_OK;
  534. }


  535. static void
  536. ngx_http_variable_request_set_size(ngx_http_request_t *r,
  537.     ngx_http_variable_value_t *v, uintptr_t data)
  538. {
  539.     ssize_t    s, *sp;
  540.     ngx_str_t  val;

  541.     val.len = v->len;
  542.     val.data = v->data;

  543.     s = ngx_parse_size(&val);

  544.     if (s == NGX_ERROR) {
  545.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  546.                       "invalid size \"%V\"", &val);
  547.         return;
  548.     }

  549.     sp = (ssize_t *) ((char *) r + data);

  550.     *sp = s;

  551.     return;
  552. }


  553. static ngx_int_t
  554. ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  555.     uintptr_t data)
  556. {
  557.     ngx_table_elt_t  *h;

  558.     h = *(ngx_table_elt_t **) ((char *) r + data);

  559.     if (h) {
  560.         v->len = h->value.len;
  561.         v->valid = 1;
  562.         v->no_cacheable = 0;
  563.         v->not_found = 0;
  564.         v->data = h->value.data;

  565.     } else {
  566.         v->not_found = 1;
  567.     }

  568.     return NGX_OK;
  569. }


  570. static ngx_int_t
  571. ngx_http_variable_cookies(ngx_http_request_t *r,
  572.     ngx_http_variable_value_t *v, uintptr_t data)
  573. {
  574.     return ngx_http_variable_headers_internal(r, v, data, ';');
  575. }


  576. static ngx_int_t
  577. ngx_http_variable_headers(ngx_http_request_t *r,
  578.     ngx_http_variable_value_t *v, uintptr_t data)
  579. {
  580.     return ngx_http_variable_headers_internal(r, v, data, ',');
  581. }


  582. static ngx_int_t
  583. ngx_http_variable_headers_internal(ngx_http_request_t *r,
  584.     ngx_http_variable_value_t *v, uintptr_t data, u_char sep)
  585. {
  586.     size_t             len;
  587.     u_char            *p, *end;
  588.     ngx_uint_t         i, n;
  589.     ngx_array_t       *a;
  590.     ngx_table_elt_t  **h;

  591.     a = (ngx_array_t *) ((char *) r + data);

  592.     n = a->nelts;
  593.     h = a->elts;

  594.     len = 0;

  595.     for (i = 0; i < n; i++) {

  596.         if (h[i]->hash == 0) {
  597.             continue;
  598.         }

  599.         len += h[i]->value.len + 2;
  600.     }

  601.     if (len == 0) {
  602.         v->not_found = 1;
  603.         return NGX_OK;
  604.     }

  605.     len -= 2;

  606.     v->valid = 1;
  607.     v->no_cacheable = 0;
  608.     v->not_found = 0;

  609.     if (n == 1) {
  610.         v->len = (*h)->value.len;
  611.         v->data = (*h)->value.data;

  612.         return NGX_OK;
  613.     }

  614.     p = ngx_pnalloc(r->pool, len);
  615.     if (p == NULL) {
  616.         return NGX_ERROR;
  617.     }

  618.     v->len = len;
  619.     v->data = p;

  620.     end = p + len;

  621.     for (i = 0; /* void */ ; i++) {

  622.         if (h[i]->hash == 0) {
  623.             continue;
  624.         }

  625.         p = ngx_copy(p, h[i]->value.data, h[i]->value.len);

  626.         if (p == end) {
  627.             break;
  628.         }

  629.         *p++ = sep; *p++ = ' ';
  630.     }

  631.     return NGX_OK;
  632. }


  633. static ngx_int_t
  634. ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
  635.     ngx_http_variable_value_t *v, uintptr_t data)
  636. {
  637.     return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
  638.                                             &r->headers_in.headers.part,
  639.                                             sizeof("http_") - 1);
  640. }


  641. static ngx_int_t
  642. ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
  643.     ngx_http_variable_value_t *v, uintptr_t data)
  644. {
  645.     return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
  646.                                             &r->headers_out.headers.part,
  647.                                             sizeof("sent_http_") - 1);
  648. }


  649. ngx_int_t
  650. ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var,
  651.     ngx_list_part_t *part, size_t prefix)
  652. {
  653.     u_char            ch;
  654.     ngx_uint_t        i, n;
  655.     ngx_table_elt_t  *header;

  656.     header = part->elts;

  657.     for (i = 0; /* void */ ; i++) {

  658.         if (i >= part->nelts) {
  659.             if (part->next == NULL) {
  660.                 break;
  661.             }

  662.             part = part->next;
  663.             header = part->elts;
  664.             i = 0;
  665.         }

  666.         if (header[i].hash == 0) {
  667.             continue;
  668.         }

  669.         for (n = 0; n + prefix < var->len && n < header[i].key.len; n++) {
  670.             ch = header[i].key.data[n];

  671.             if (ch >= 'A' && ch <= 'Z') {
  672.                 ch |= 0x20;

  673.             } else if (ch == '-') {
  674.                 ch = '_';
  675.             }

  676.             if (var->data[n + prefix] != ch) {
  677.                 break;
  678.             }
  679.         }

  680.         if (n + prefix == var->len && n == header[i].key.len) {
  681.             v->len = header[i].value.len;
  682.             v->valid = 1;
  683.             v->no_cacheable = 0;
  684.             v->not_found = 0;
  685.             v->data = header[i].value.data;

  686.             return NGX_OK;
  687.         }
  688.     }

  689.     v->not_found = 1;

  690.     return NGX_OK;
  691. }


  692. static ngx_int_t
  693. ngx_http_variable_request_line(ngx_http_request_t *r,
  694.     ngx_http_variable_value_t *v, uintptr_t data)
  695. {
  696.     u_char  *p, *s;

  697.     s = r->request_line.data;

  698.     if (s == NULL) {
  699.         s = r->request_start;

  700.         if (s == NULL) {
  701.             v->not_found = 1;
  702.             return NGX_OK;
  703.         }

  704.         for (p = s; p < r->header_in->last; p++) {
  705.             if (*p == CR || *p == LF) {
  706.                 break;
  707.             }
  708.         }

  709.         r->request_line.len = p - s;
  710.         r->request_line.data = s;
  711.     }

  712.     v->len = r->request_line.len;
  713.     v->valid = 1;
  714.     v->no_cacheable = 0;
  715.     v->not_found = 0;
  716.     v->data = s;

  717.     return NGX_OK;
  718. }


  719. static ngx_int_t
  720. ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  721.     uintptr_t data)
  722. {
  723.     ngx_str_t *name = (ngx_str_t *) data;

  724.     ngx_str_t  cookie, s;

  725.     s.len = name->len - (sizeof("cookie_") - 1);
  726.     s.data = name->data + sizeof("cookie_") - 1;

  727.     if (ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &s, &cookie)
  728.         == NGX_DECLINED)
  729.     {
  730.         v->not_found = 1;
  731.         return NGX_OK;
  732.     }

  733.     v->len = cookie.len;
  734.     v->valid = 1;
  735.     v->no_cacheable = 0;
  736.     v->not_found = 0;
  737.     v->data = cookie.data;

  738.     return NGX_OK;
  739. }


  740. static ngx_int_t
  741. ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  742.     uintptr_t data)
  743. {
  744.     ngx_str_t *name = (ngx_str_t *) data;

  745.     u_char     *arg;
  746.     size_t      len;
  747.     ngx_str_t   value;

  748.     len = name->len - (sizeof("arg_") - 1);
  749.     arg = name->data + sizeof("arg_") - 1;

  750.     if (ngx_http_arg(r, arg, len, &value) != NGX_OK) {
  751.         v->not_found = 1;
  752.         return NGX_OK;
  753.     }

  754.     v->data = value.data;
  755.     v->len = value.len;
  756.     v->valid = 1;
  757.     v->no_cacheable = 0;
  758.     v->not_found = 0;

  759.     return NGX_OK;
  760. }


  761. #if (NGX_HAVE_TCP_INFO)

  762. static ngx_int_t
  763. ngx_http_variable_tcpinfo(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  764.     uintptr_t data)
  765. {
  766.     struct tcp_info  ti;
  767.     socklen_t        len;
  768.     uint32_t         value;

  769.     len = sizeof(struct tcp_info);
  770.     if (getsockopt(r->connection->fd, IPPROTO_TCP, TCP_INFO, &ti, &len) == -1) {
  771.         v->not_found = 1;
  772.         return NGX_OK;
  773.     }

  774.     v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN);
  775.     if (v->data == NULL) {
  776.         return NGX_ERROR;
  777.     }

  778.     switch (data) {
  779.     case 0:
  780.         value = ti.tcpi_rtt;
  781.         break;

  782.     case 1:
  783.         value = ti.tcpi_rttvar;
  784.         break;

  785.     case 2:
  786.         value = ti.tcpi_snd_cwnd;
  787.         break;

  788.     case 3:
  789.         value = ti.tcpi_rcv_space;
  790.         break;

  791.     /* suppress warning */
  792.     default:
  793.         value = 0;
  794.         break;
  795.     }

  796.     v->len = ngx_sprintf(v->data, "%uD", value) - v->data;
  797.     v->valid = 1;
  798.     v->no_cacheable = 0;
  799.     v->not_found = 0;

  800.     return NGX_OK;
  801. }

  802. #endif


  803. static ngx_int_t
  804. ngx_http_variable_content_length(ngx_http_request_t *r,
  805.     ngx_http_variable_value_t *v, uintptr_t data)
  806. {
  807.     u_char  *p;

  808.     if (r->headers_in.content_length) {
  809.         v->len = r->headers_in.content_length->value.len;
  810.         v->data = r->headers_in.content_length->value.data;
  811.         v->valid = 1;
  812.         v->no_cacheable = 0;
  813.         v->not_found = 0;

  814.     } else if (r->headers_in.content_length_n >= 0) {
  815.         p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
  816.         if (p == NULL) {
  817.             return NGX_ERROR;
  818.         }

  819.         v->len = ngx_sprintf(p, "%O", r->headers_in.content_length_n) - p;
  820.         v->data = p;
  821.         v->valid = 1;
  822.         v->no_cacheable = 0;
  823.         v->not_found = 0;

  824.     } else {
  825.         v->not_found = 1;
  826.     }

  827.     return NGX_OK;
  828. }


  829. static ngx_int_t
  830. ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  831.     uintptr_t data)
  832. {
  833.     ngx_http_core_srv_conf_t  *cscf;

  834.     if (r->headers_in.server.len) {
  835.         v->len = r->headers_in.server.len;
  836.         v->data = r->headers_in.server.data;

  837.     } else {
  838.         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);

  839.         v->len = cscf->server_name.len;
  840.         v->data = cscf->server_name.data;
  841.     }

  842.     v->valid = 1;
  843.     v->no_cacheable = 0;
  844.     v->not_found = 0;

  845.     return NGX_OK;
  846. }


  847. static ngx_int_t
  848. ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
  849.     ngx_http_variable_value_t *v, uintptr_t data)
  850. {
  851.     struct sockaddr_in   *sin;
  852. #if (NGX_HAVE_INET6)
  853.     struct sockaddr_in6  *sin6;
  854. #endif

  855.     switch (r->connection->sockaddr->sa_family) {

  856. #if (NGX_HAVE_INET6)
  857.     case AF_INET6:
  858.         sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;

  859.         v->len = sizeof(struct in6_addr);
  860.         v->valid = 1;
  861.         v->no_cacheable = 0;
  862.         v->not_found = 0;
  863.         v->data = sin6->sin6_addr.s6_addr;

  864.         break;
  865. #endif

  866.     default: /* AF_INET */
  867.         sin = (struct sockaddr_in *) r->connection->sockaddr;

  868.         v->len = sizeof(in_addr_t);
  869.         v->valid = 1;
  870.         v->no_cacheable = 0;
  871.         v->not_found = 0;
  872.         v->data = (u_char *) &sin->sin_addr;

  873.         break;
  874.     }

  875.     return NGX_OK;
  876. }


  877. static ngx_int_t
  878. ngx_http_variable_remote_addr(ngx_http_request_t *r,
  879.     ngx_http_variable_value_t *v, uintptr_t data)
  880. {
  881.     v->len = r->connection->addr_text.len;
  882.     v->valid = 1;
  883.     v->no_cacheable = 0;
  884.     v->not_found = 0;
  885.     v->data = r->connection->addr_text.data;

  886.     return NGX_OK;
  887. }


  888. static ngx_int_t
  889. ngx_http_variable_remote_port(ngx_http_request_t *r,
  890.     ngx_http_variable_value_t *v, uintptr_t data)
  891. {
  892.     ngx_uint_t            port;
  893.     struct sockaddr_in   *sin;
  894. #if (NGX_HAVE_INET6)
  895.     struct sockaddr_in6  *sin6;
  896. #endif

  897.     v->len = 0;
  898.     v->valid = 1;
  899.     v->no_cacheable = 0;
  900.     v->not_found = 0;

  901.     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
  902.     if (v->data == NULL) {
  903.         return NGX_ERROR;
  904.     }

  905.     switch (r->connection->sockaddr->sa_family) {

  906. #if (NGX_HAVE_INET6)
  907.     case AF_INET6:
  908.         sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
  909.         port = ntohs(sin6->sin6_port);
  910.         break;
  911. #endif

  912. #if (NGX_HAVE_UNIX_DOMAIN)
  913.     case AF_UNIX:
  914.         port = 0;
  915.         break;
  916. #endif

  917.     default: /* AF_INET */
  918.         sin = (struct sockaddr_in *) r->connection->sockaddr;
  919.         port = ntohs(sin->sin_port);
  920.         break;
  921.     }

  922.     if (port > 0 && port < 65536) {
  923.         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
  924.     }

  925.     return NGX_OK;
  926. }


  927. static ngx_int_t
  928. ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
  929.     ngx_http_variable_value_t *v, uintptr_t data)
  930. {
  931.     v->len = r->connection->proxy_protocol_addr.len;
  932.     v->valid = 1;
  933.     v->no_cacheable = 0;
  934.     v->not_found = 0;
  935.     v->data = r->connection->proxy_protocol_addr.data;

  936.     return NGX_OK;
  937. }


  938. static ngx_int_t
  939. ngx_http_variable_server_addr(ngx_http_request_t *r,
  940.     ngx_http_variable_value_t *v, uintptr_t data)
  941. {
  942.     ngx_str_t  s;
  943.     u_char     addr[NGX_SOCKADDR_STRLEN];

  944.     s.len = NGX_SOCKADDR_STRLEN;
  945.     s.data = addr;

  946.     if (ngx_connection_local_sockaddr(r->connection, &s, 0) != NGX_OK) {
  947.         return NGX_ERROR;
  948.     }

  949.     s.data = ngx_pnalloc(r->pool, s.len);
  950.     if (s.data == NULL) {
  951.         return NGX_ERROR;
  952.     }

  953.     ngx_memcpy(s.data, addr, s.len);

  954.     v->len = s.len;
  955.     v->valid = 1;
  956.     v->no_cacheable = 0;
  957.     v->not_found = 0;
  958.     v->data = s.data;

  959.     return NGX_OK;
  960. }


  961. static ngx_int_t
  962. ngx_http_variable_server_port(ngx_http_request_t *r,
  963.     ngx_http_variable_value_t *v, uintptr_t data)
  964. {
  965.     ngx_uint_t            port;
  966.     struct sockaddr_in   *sin;
  967. #if (NGX_HAVE_INET6)
  968.     struct sockaddr_in6  *sin6;
  969. #endif

  970.     v->len = 0;
  971.     v->valid = 1;
  972.     v->no_cacheable = 0;
  973.     v->not_found = 0;

  974.     if (ngx_connection_local_sockaddr(r->connection, NULL, 0) != NGX_OK) {
  975.         return NGX_ERROR;
  976.     }

  977.     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
  978.     if (v->data == NULL) {
  979.         return NGX_ERROR;
  980.     }

  981.     switch (r->connection->local_sockaddr->sa_family) {

  982. #if (NGX_HAVE_INET6)
  983.     case AF_INET6:
  984.         sin6 = (struct sockaddr_in6 *) r->connection->local_sockaddr;
  985.         port = ntohs(sin6->sin6_port);
  986.         break;
  987. #endif

  988. #if (NGX_HAVE_UNIX_DOMAIN)
  989.     case AF_UNIX:
  990.         port = 0;
  991.         break;
  992. #endif

  993.     default: /* AF_INET */
  994.         sin = (struct sockaddr_in *) r->connection->local_sockaddr;
  995.         port = ntohs(sin->sin_port);
  996.         break;
  997.     }

  998.     if (port > 0 && port < 65536) {
  999.         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
  1000.     }

  1001.     return NGX_OK;
  1002. }


  1003. static ngx_int_t
  1004. ngx_http_variable_scheme(ngx_http_request_t *r,
  1005.     ngx_http_variable_value_t *v, uintptr_t data)
  1006. {
  1007. #if (NGX_HTTP_SSL)

  1008.     if (r->connection->ssl) {
  1009.         v->len = sizeof("https") - 1;
  1010.         v->valid = 1;
  1011.         v->no_cacheable = 0;
  1012.         v->not_found = 0;
  1013.         v->data = (u_char *) "https";

  1014.         return NGX_OK;
  1015.     }

  1016. #endif

  1017.     v->len = sizeof("http") - 1;
  1018.     v->valid = 1;
  1019.     v->no_cacheable = 0;
  1020.     v->not_found = 0;
  1021.     v->data = (u_char *) "http";

  1022.     return NGX_OK;
  1023. }


  1024. static ngx_int_t
  1025. ngx_http_variable_https(ngx_http_request_t *r,
  1026.     ngx_http_variable_value_t *v, uintptr_t data)
  1027. {
  1028. #if (NGX_HTTP_SSL)

  1029.     if (r->connection->ssl) {
  1030.         v->len = sizeof("on") - 1;
  1031.         v->valid = 1;
  1032.         v->no_cacheable = 0;
  1033.         v->not_found = 0;
  1034.         v->data = (u_char *) "on";

  1035.         return NGX_OK;
  1036.     }

  1037. #endif

  1038.     *v = ngx_http_variable_null_value;

  1039.     return NGX_OK;
  1040. }


  1041. static void
  1042. ngx_http_variable_set_args(ngx_http_request_t *r,
  1043.     ngx_http_variable_value_t *v, uintptr_t data)
  1044. {
  1045.     r->args.len = v->len;
  1046.     r->args.data = v->data;
  1047.     r->valid_unparsed_uri = 0;
  1048. }


  1049. static ngx_int_t
  1050. ngx_http_variable_is_args(ngx_http_request_t *r,
  1051.     ngx_http_variable_value_t *v, uintptr_t data)
  1052. {
  1053.     v->valid = 1;
  1054.     v->no_cacheable = 0;
  1055.     v->not_found = 0;

  1056.     if (r->args.len == 0) {
  1057.         v->len = 0;
  1058.         v->data = NULL;
  1059.         return NGX_OK;
  1060.     }

  1061.     v->len = 1;
  1062.     v->data = (u_char *) "?";

  1063.     return NGX_OK;
  1064. }


  1065. static ngx_int_t
  1066. ngx_http_variable_document_root(ngx_http_request_t *r,
  1067.     ngx_http_variable_value_t *v, uintptr_t data)
  1068. {
  1069.     ngx_str_t                  path;
  1070.     ngx_http_core_loc_conf_t  *clcf;

  1071.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1072.     if (clcf->root_lengths == NULL) {
  1073.         v->len = clcf->root.len;
  1074.         v->valid = 1;
  1075.         v->no_cacheable = 0;
  1076.         v->not_found = 0;
  1077.         v->data = clcf->root.data;

  1078.     } else {
  1079.         if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 0,
  1080.                                 clcf->root_values->elts)
  1081.             == NULL)
  1082.         {
  1083.             return NGX_ERROR;
  1084.         }

  1085.         if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, &path)
  1086.             != NGX_OK)
  1087.         {
  1088.             return NGX_ERROR;
  1089.         }

  1090.         v->len = path.len;
  1091.         v->valid = 1;
  1092.         v->no_cacheable = 0;
  1093.         v->not_found = 0;
  1094.         v->data = path.data;
  1095.     }

  1096.     return NGX_OK;
  1097. }


  1098. static ngx_int_t
  1099. ngx_http_variable_realpath_root(ngx_http_request_t *r,
  1100.     ngx_http_variable_value_t *v, uintptr_t data)
  1101. {
  1102.     u_char                    *real;
  1103.     size_t                     len;
  1104.     ngx_str_t                  path;
  1105.     ngx_http_core_loc_conf_t  *clcf;
  1106. #if (NGX_HAVE_MAX_PATH)
  1107.     u_char                     buffer[NGX_MAX_PATH];
  1108. #endif

  1109.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1110.     if (clcf->root_lengths == NULL) {
  1111.         path = clcf->root;

  1112.     } else {
  1113.         if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 1,
  1114.                                 clcf->root_values->elts)
  1115.             == NULL)
  1116.         {
  1117.             return NGX_ERROR;
  1118.         }

  1119.         path.data[path.len - 1] = '\0';

  1120.         if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, &path)
  1121.             != NGX_OK)
  1122.         {
  1123.             return NGX_ERROR;
  1124.         }
  1125.     }

  1126. #if (NGX_HAVE_MAX_PATH)
  1127.     real = buffer;
  1128. #else
  1129.     real = NULL;
  1130. #endif

  1131.     real = ngx_realpath(path.data, real);

  1132.     if (real == NULL) {
  1133.         ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
  1134.                       ngx_realpath_n " \"%s\" failed", path.data);
  1135.         return NGX_ERROR;
  1136.     }

  1137.     len = ngx_strlen(real);

  1138.     v->data = ngx_pnalloc(r->pool, len);
  1139.     if (v->data == NULL) {
  1140. #if !(NGX_HAVE_MAX_PATH)
  1141.         ngx_free(real);
  1142. #endif
  1143.         return NGX_ERROR;
  1144.     }

  1145.     v->len = len;
  1146.     v->valid = 1;
  1147.     v->no_cacheable = 0;
  1148.     v->not_found = 0;

  1149.     ngx_memcpy(v->data, real, len);

  1150. #if !(NGX_HAVE_MAX_PATH)
  1151.     ngx_free(real);
  1152. #endif

  1153.     return NGX_OK;
  1154. }


  1155. static ngx_int_t
  1156. ngx_http_variable_request_filename(ngx_http_request_t *r,
  1157.     ngx_http_variable_value_t *v, uintptr_t data)
  1158. {
  1159.     size_t     root;
  1160.     ngx_str_t  path;

  1161.     if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
  1162.         return NGX_ERROR;
  1163.     }

  1164.     /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */

  1165.     v->len = path.len - 1;
  1166.     v->valid = 1;
  1167.     v->no_cacheable = 0;
  1168.     v->not_found = 0;
  1169.     v->data = path.data;

  1170.     return NGX_OK;
  1171. }


  1172. static ngx_int_t
  1173. ngx_http_variable_server_name(ngx_http_request_t *r,
  1174.     ngx_http_variable_value_t *v, uintptr_t data)
  1175. {
  1176.     ngx_http_core_srv_conf_t  *cscf;

  1177.     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);

  1178.     v->len = cscf->server_name.len;
  1179.     v->valid = 1;
  1180.     v->no_cacheable = 0;
  1181.     v->not_found = 0;
  1182.     v->data = cscf->server_name.data;

  1183.     return NGX_OK;
  1184. }


  1185. static ngx_int_t
  1186. ngx_http_variable_request_method(ngx_http_request_t *r,
  1187.     ngx_http_variable_value_t *v, uintptr_t data)
  1188. {
  1189.     if (r->main->method_name.data) {
  1190.         v->len = r->main->method_name.len;
  1191.         v->valid = 1;
  1192.         v->no_cacheable = 0;
  1193.         v->not_found = 0;
  1194.         v->data = r->main->method_name.data;

  1195.     } else {
  1196.         v->not_found = 1;
  1197.     }

  1198.     return NGX_OK;
  1199. }


  1200. static ngx_int_t
  1201. ngx_http_variable_remote_user(ngx_http_request_t *r,
  1202.     ngx_http_variable_value_t *v, uintptr_t data)
  1203. {
  1204.     ngx_int_t  rc;

  1205.     rc = ngx_http_auth_basic_user(r);

  1206.     if (rc == NGX_DECLINED) {
  1207.         v->not_found = 1;
  1208.         return NGX_OK;
  1209.     }

  1210.     if (rc == NGX_ERROR) {
  1211.         return NGX_ERROR;
  1212.     }

  1213.     v->len = r->headers_in.user.len;
  1214.     v->valid = 1;
  1215.     v->no_cacheable = 0;
  1216.     v->not_found = 0;
  1217.     v->data = r->headers_in.user.data;

  1218.     return NGX_OK;
  1219. }


  1220. static ngx_int_t
  1221. ngx_http_variable_bytes_sent(ngx_http_request_t *r,
  1222.     ngx_http_variable_value_t *v, uintptr_t data)
  1223. {
  1224.     u_char  *p;

  1225.     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
  1226.     if (p == NULL) {
  1227.         return NGX_ERROR;
  1228.     }

  1229.     v->len = ngx_sprintf(p, "%O", r->connection->sent) - p;
  1230.     v->valid = 1;
  1231.     v->no_cacheable = 0;
  1232.     v->not_found = 0;
  1233.     v->data = p;

  1234.     return NGX_OK;
  1235. }


  1236. static ngx_int_t
  1237. ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
  1238.     ngx_http_variable_value_t *v, uintptr_t data)
  1239. {
  1240.     off_t    sent;
  1241.     u_char  *p;

  1242.     sent = r->connection->sent - r->header_size;

  1243.     if (sent < 0) {
  1244.         sent = 0;
  1245.     }

  1246.     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
  1247.     if (p == NULL) {
  1248.         return NGX_ERROR;
  1249.     }

  1250.     v->len = ngx_sprintf(p, "%O", sent) - p;
  1251.     v->valid = 1;
  1252.     v->no_cacheable = 0;
  1253.     v->not_found = 0;
  1254.     v->data = p;

  1255.     return NGX_OK;
  1256. }


  1257. static ngx_int_t
  1258. ngx_http_variable_pipe(ngx_http_request_t *r,
  1259.     ngx_http_variable_value_t *v, uintptr_t data)
  1260. {
  1261.     v->data = (u_char *) (r->pipeline ? "p" : ".");
  1262.     v->len = 1;
  1263.     v->valid = 1;
  1264.     v->no_cacheable = 0;
  1265.     v->not_found = 0;

  1266.     return NGX_OK;
  1267. }


  1268. static ngx_int_t
  1269. ngx_http_variable_status(ngx_http_request_t *r,
  1270.     ngx_http_variable_value_t *v, uintptr_t data)
  1271. {
  1272.     ngx_uint_t  status;

  1273.     v->data = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
  1274.     if (v->data == NULL) {
  1275.         return NGX_ERROR;
  1276.     }

  1277.     if (r->err_status) {
  1278.         status = r->err_status;

  1279.     } else if (r->headers_out.status) {
  1280.         status = r->headers_out.status;

  1281.     } else if (r->http_version == NGX_HTTP_VERSION_9) {
  1282.         status = 9;

  1283.     } else {
  1284.         status = 0;
  1285.     }

  1286.     v->len = ngx_sprintf(v->data, "%03ui", status) - v->data;
  1287.     v->valid = 1;
  1288.     v->no_cacheable = 0;
  1289.     v->not_found = 0;

  1290.     return NGX_OK;
  1291. }


  1292. static ngx_int_t
  1293. ngx_http_variable_sent_content_type(ngx_http_request_t *r,
  1294.     ngx_http_variable_value_t *v, uintptr_t data)
  1295. {
  1296.     if (r->headers_out.content_type.len) {
  1297.         v->len = r->headers_out.content_type.len;
  1298.         v->valid = 1;
  1299.         v->no_cacheable = 0;
  1300.         v->not_found = 0;
  1301.         v->data = r->headers_out.content_type.data;

  1302.     } else {
  1303.         v->not_found = 1;
  1304.     }

  1305.     return NGX_OK;
  1306. }


  1307. static ngx_int_t
  1308. ngx_http_variable_sent_content_length(ngx_http_request_t *r,
  1309.     ngx_http_variable_value_t *v, uintptr_t data)
  1310. {
  1311.     u_char  *p;

  1312.     if (r->headers_out.content_length) {
  1313.         v->len = r->headers_out.content_length->value.len;
  1314.         v->valid = 1;
  1315.         v->no_cacheable = 0;
  1316.         v->not_found = 0;
  1317.         v->data = r->headers_out.content_length->value.data;

  1318.         return NGX_OK;
  1319.     }

  1320.     if (r->headers_out.content_length_n >= 0) {
  1321.         p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
  1322.         if (p == NULL) {
  1323.             return NGX_ERROR;
  1324.         }

  1325.         v->len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) - p;
  1326.         v->valid = 1;
  1327.         v->no_cacheable = 0;
  1328.         v->not_found = 0;
  1329.         v->data = p;

  1330.         return NGX_OK;
  1331.     }

  1332.     v->not_found = 1;

  1333.     return NGX_OK;
  1334. }


  1335. static ngx_int_t
  1336. ngx_http_variable_sent_location(ngx_http_request_t *r,
  1337.     ngx_http_variable_value_t *v, uintptr_t data)
  1338. {
  1339.     ngx_str_t  name;

  1340.     if (r->headers_out.location) {
  1341.         v->len = r->headers_out.location->value.len;
  1342.         v->valid = 1;
  1343.         v->no_cacheable = 0;
  1344.         v->not_found = 0;
  1345.         v->data = r->headers_out.location->value.data;

  1346.         return NGX_OK;
  1347.     }

  1348.     ngx_str_set(&name, "sent_http_location");

  1349.     return ngx_http_variable_unknown_header(v, &name,
  1350.                                             &r->headers_out.headers.part,
  1351.                                             sizeof("sent_http_") - 1);
  1352. }


  1353. static ngx_int_t
  1354. ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
  1355.     ngx_http_variable_value_t *v, uintptr_t data)
  1356. {
  1357.     u_char  *p;

  1358.     if (r->headers_out.last_modified) {
  1359.         v->len = r->headers_out.last_modified->value.len;
  1360.         v->valid = 1;
  1361.         v->no_cacheable = 0;
  1362.         v->not_found = 0;
  1363.         v->data = r->headers_out.last_modified->value.data;

  1364.         return NGX_OK;
  1365.     }

  1366.     if (r->headers_out.last_modified_time >= 0) {
  1367.         p = ngx_pnalloc(r->pool, sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1);
  1368.         if (p == NULL) {
  1369.             return NGX_ERROR;
  1370.         }

  1371.         v->len = ngx_http_time(p, r->headers_out.last_modified_time) - p;
  1372.         v->valid = 1;
  1373.         v->no_cacheable = 0;
  1374.         v->not_found = 0;
  1375.         v->data = p;

  1376.         return NGX_OK;
  1377.     }

  1378.     v->not_found = 1;

  1379.     return NGX_OK;
  1380. }


  1381. static ngx_int_t
  1382. ngx_http_variable_sent_connection(ngx_http_request_t *r,
  1383.     ngx_http_variable_value_t *v, uintptr_t data)
  1384. {
  1385.     size_t   len;
  1386.     char    *p;

  1387.     if (r->headers_out.status == NGX_HTTP_SWITCHING_PROTOCOLS) {
  1388.         len = sizeof("upgrade") - 1;
  1389.         p = "upgrade";

  1390.     } else if (r->keepalive) {
  1391.         len = sizeof("keep-alive") - 1;
  1392.         p = "keep-alive";

  1393.     } else {
  1394.         len = sizeof("close") - 1;
  1395.         p = "close";
  1396.     }

  1397.     v->len = len;
  1398.     v->valid = 1;
  1399.     v->no_cacheable = 0;
  1400.     v->not_found = 0;
  1401.     v->data = (u_char *) p;

  1402.     return NGX_OK;
  1403. }


  1404. static ngx_int_t
  1405. ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
  1406.     ngx_http_variable_value_t *v, uintptr_t data)
  1407. {
  1408.     u_char                    *p;
  1409.     ngx_http_core_loc_conf_t  *clcf;

  1410.     if (r->keepalive) {
  1411.         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1412.         if (clcf->keepalive_header) {

  1413.             p = ngx_pnalloc(r->pool, sizeof("timeout=") - 1 + NGX_TIME_T_LEN);
  1414.             if (p == NULL) {
  1415.                 return NGX_ERROR;
  1416.             }

  1417.             v->len = ngx_sprintf(p, "timeout=%T", clcf->keepalive_header) - p;
  1418.             v->valid = 1;
  1419.             v->no_cacheable = 0;
  1420.             v->not_found = 0;
  1421.             v->data = p;

  1422.             return NGX_OK;
  1423.         }
  1424.     }

  1425.     v->not_found = 1;

  1426.     return NGX_OK;
  1427. }


  1428. static ngx_int_t
  1429. ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
  1430.     ngx_http_variable_value_t *v, uintptr_t data)
  1431. {
  1432.     if (r->chunked) {
  1433.         v->len = sizeof("chunked") - 1;
  1434.         v->valid = 1;
  1435.         v->no_cacheable = 0;
  1436.         v->not_found = 0;
  1437.         v->data = (u_char *) "chunked";

  1438.     } else {
  1439.         v->not_found = 1;
  1440.     }

  1441.     return NGX_OK;
  1442. }


  1443. static ngx_int_t
  1444. ngx_http_variable_request_completion(ngx_http_request_t *r,
  1445.     ngx_http_variable_value_t *v, uintptr_t data)
  1446. {
  1447.     if (r->request_complete) {
  1448.         v->len = 2;
  1449.         v->valid = 1;
  1450.         v->no_cacheable = 0;
  1451.         v->not_found = 0;
  1452.         v->data = (u_char *) "OK";

  1453.         return NGX_OK;
  1454.     }

  1455.     v->len = 0;
  1456.     v->valid = 1;
  1457.     v->no_cacheable = 0;
  1458.     v->not_found = 0;
  1459.     v->data = (u_char *) "";

  1460.     return NGX_OK;
  1461. }


  1462. static ngx_int_t
  1463. ngx_http_variable_request_body(ngx_http_request_t *r,
  1464.     ngx_http_variable_value_t *v, uintptr_t data)
  1465. {
  1466.     u_char       *p;
  1467.     size_t        len;
  1468.     ngx_buf_t    *buf;
  1469.     ngx_chain_t  *cl;

  1470.     if (r->request_body == NULL
  1471.         || r->request_body->bufs == NULL
  1472.         || r->request_body->temp_file)
  1473.     {
  1474.         v->not_found = 1;

  1475.         return NGX_OK;
  1476.     }

  1477.     cl = r->request_body->bufs;
  1478.     buf = cl->buf;

  1479.     if (cl->next == NULL) {
  1480.         v->len = buf->last - buf->pos;
  1481.         v->valid = 1;
  1482.         v->no_cacheable = 0;
  1483.         v->not_found = 0;
  1484.         v->data = buf->pos;

  1485.         return NGX_OK;
  1486.     }

  1487.     len = buf->last - buf->pos;
  1488.     cl = cl->next;

  1489.     for ( /* void */ ; cl; cl = cl->next) {
  1490.         buf = cl->buf;
  1491.         len += buf->last - buf->pos;
  1492.     }

  1493.     p = ngx_pnalloc(r->pool, len);
  1494.     if (p == NULL) {
  1495.         return NGX_ERROR;
  1496.     }

  1497.     v->data = p;
  1498.     cl = r->request_body->bufs;

  1499.     for ( /* void */ ; cl; cl = cl->next) {
  1500.         buf = cl->buf;
  1501.         p = ngx_cpymem(p, buf->pos, buf->last - buf->pos);
  1502.     }

  1503.     v->len = len;
  1504.     v->valid = 1;
  1505.     v->no_cacheable = 0;
  1506.     v->not_found = 0;

  1507.     return NGX_OK;
  1508. }


  1509. static ngx_int_t
  1510. ngx_http_variable_request_body_file(ngx_http_request_t *r,
  1511.     ngx_http_variable_value_t *v, uintptr_t data)
  1512. {
  1513.     if (r->request_body == NULL || r->request_body->temp_file == NULL) {
  1514.         v->not_found = 1;

  1515.         return NGX_OK;
  1516.     }

  1517.     v->len = r->request_body->temp_file->file.name.len;
  1518.     v->valid = 1;
  1519.     v->no_cacheable = 0;
  1520.     v->not_found = 0;
  1521.     v->data = r->request_body->temp_file->file.name.data;

  1522.     return NGX_OK;
  1523. }


  1524. static ngx_int_t
  1525. ngx_http_variable_request_length(ngx_http_request_t *r,
  1526.     ngx_http_variable_value_t *v, uintptr_t data)
  1527. {
  1528.     u_char  *p;

  1529.     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
  1530.     if (p == NULL) {
  1531.         return NGX_ERROR;
  1532.     }

  1533.     v->len = ngx_sprintf(p, "%O", r->request_length) - p;
  1534.     v->valid = 1;
  1535.     v->no_cacheable = 0;
  1536.     v->not_found = 0;
  1537.     v->data = p;

  1538.     return NGX_OK;
  1539. }


  1540. static ngx_int_t
  1541. ngx_http_variable_request_time(ngx_http_request_t *r,
  1542.     ngx_http_variable_value_t *v, uintptr_t data)
  1543. {
  1544.     u_char          *p;
  1545.     ngx_time_t      *tp;
  1546.     ngx_msec_int_t   ms;

  1547.     p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4);
  1548.     if (p == NULL) {
  1549.         return NGX_ERROR;
  1550.     }

  1551.     tp = ngx_timeofday();

  1552.     ms = (ngx_msec_int_t)
  1553.              ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec));
  1554.     ms = ngx_max(ms, 0);

  1555.     v->len = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000) - p;
  1556.     v->valid = 1;
  1557.     v->no_cacheable = 0;
  1558.     v->not_found = 0;
  1559.     v->data = p;

  1560.     return NGX_OK;
  1561. }


  1562. static ngx_int_t
  1563. ngx_http_variable_connection(ngx_http_request_t *r,
  1564.     ngx_http_variable_value_t *v, uintptr_t data)
  1565. {
  1566.     u_char  *p;

  1567.     p = ngx_pnalloc(r->pool, NGX_ATOMIC_T_LEN);
  1568.     if (p == NULL) {
  1569.         return NGX_ERROR;
  1570.     }

  1571.     v->len = ngx_sprintf(p, "%uA", r->connection->number) - p;
  1572.     v->valid = 1;
  1573.     v->no_cacheable = 0;
  1574.     v->not_found = 0;
  1575.     v->data = p;

  1576.     return NGX_OK;
  1577. }


  1578. static ngx_int_t
  1579. ngx_http_variable_connection_requests(ngx_http_request_t *r,
  1580.     ngx_http_variable_value_t *v, uintptr_t data)
  1581. {
  1582.     u_char  *p;

  1583.     p = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
  1584.     if (p == NULL) {
  1585.         return NGX_ERROR;
  1586.     }

  1587.     v->len = ngx_sprintf(p, "%ui", r->connection->requests) - p;
  1588.     v->valid = 1;
  1589.     v->no_cacheable = 0;
  1590.     v->not_found = 0;
  1591.     v->data = p;

  1592.     return NGX_OK;
  1593. }


  1594. static ngx_int_t
  1595. ngx_http_variable_nginx_version(ngx_http_request_t *r,
  1596.     ngx_http_variable_value_t *v, uintptr_t data)
  1597. {
  1598.     v->len = sizeof(NGINX_VERSION) - 1;
  1599.     v->valid = 1;
  1600.     v->no_cacheable = 0;
  1601.     v->not_found = 0;
  1602.     v->data = (u_char *) NGINX_VERSION;

  1603.     return NGX_OK;
  1604. }


  1605. static ngx_int_t
  1606. ngx_http_variable_hostname(ngx_http_request_t *r,
  1607.     ngx_http_variable_value_t *v, uintptr_t data)
  1608. {
  1609.     v->len = ngx_cycle->hostname.len;
  1610.     v->valid = 1;
  1611.     v->no_cacheable = 0;
  1612.     v->not_found = 0;
  1613.     v->data = ngx_cycle->hostname.data;

  1614.     return NGX_OK;
  1615. }


  1616. static ngx_int_t
  1617. ngx_http_variable_pid(ngx_http_request_t *r,
  1618.     ngx_http_variable_value_t *v, uintptr_t data)
  1619. {
  1620.     u_char  *p;

  1621.     p = ngx_pnalloc(r->pool, NGX_INT64_LEN);
  1622.     if (p == NULL) {
  1623.         return NGX_ERROR;
  1624.     }

  1625.     v->len = ngx_sprintf(p, "%P", ngx_pid) - p;
  1626.     v->valid = 1;
  1627.     v->no_cacheable = 0;
  1628.     v->not_found = 0;
  1629.     v->data = p;

  1630.     return NGX_OK;
  1631. }


  1632. static ngx_int_t
  1633. ngx_http_variable_msec(ngx_http_request_t *r,
  1634.     ngx_http_variable_value_t *v, uintptr_t data)
  1635. {
  1636.     u_char      *p;
  1637.     ngx_time_t  *tp;

  1638.     p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4);
  1639.     if (p == NULL) {
  1640.         return NGX_ERROR;
  1641.     }

  1642.     tp = ngx_timeofday();

  1643.     v->len = ngx_sprintf(p, "%T.%03M", tp->sec, tp->msec) - p;
  1644.     v->valid = 1;
  1645.     v->no_cacheable = 0;
  1646.     v->not_found = 0;
  1647.     v->data = p;

  1648.     return NGX_OK;
  1649. }


  1650. static ngx_int_t
  1651. ngx_http_variable_time_iso8601(ngx_http_request_t *r,
  1652.     ngx_http_variable_value_t *v, uintptr_t data)
  1653. {
  1654.     u_char  *p;

  1655.     p = ngx_pnalloc(r->pool, ngx_cached_http_log_iso8601.len);
  1656.     if (p == NULL) {
  1657.         return NGX_ERROR;
  1658.     }

  1659.     ngx_memcpy(p, ngx_cached_http_log_iso8601.data,
  1660.                ngx_cached_http_log_iso8601.len);

  1661.     v->len = ngx_cached_http_log_iso8601.len;
  1662.     v->valid = 1;
  1663.     v->no_cacheable = 0;
  1664.     v->not_found = 0;
  1665.     v->data = p;

  1666.     return NGX_OK;
  1667. }


  1668. static ngx_int_t
  1669. ngx_http_variable_time_local(ngx_http_request_t *r,
  1670.     ngx_http_variable_value_t *v, uintptr_t data)
  1671. {
  1672.     u_char  *p;

  1673.     p = ngx_pnalloc(r->pool, ngx_cached_http_log_time.len);
  1674.     if (p == NULL) {
  1675.         return NGX_ERROR;
  1676.     }

  1677.     ngx_memcpy(p, ngx_cached_http_log_time.data, ngx_cached_http_log_time.len);

  1678.     v->len = ngx_cached_http_log_time.len;
  1679.     v->valid = 1;
  1680.     v->no_cacheable = 0;
  1681.     v->not_found = 0;
  1682.     v->data = p;

  1683.     return NGX_OK;
  1684. }


  1685. void *
  1686. ngx_http_map_find(ngx_http_request_t *r, ngx_http_map_t *map, ngx_str_t *match)
  1687. {
  1688.     void        *value;
  1689.     u_char      *low;
  1690.     size_t       len;
  1691.     ngx_uint_t   key;

  1692.     len = match->len;

  1693.     if (len) {
  1694.         low = ngx_pnalloc(r->pool, len);
  1695.         if (low == NULL) {
  1696.             return NULL;
  1697.         }

  1698.     } else {
  1699.         low = NULL;
  1700.     }

  1701.     key = ngx_hash_strlow(low, match->data, len);

  1702.     value = ngx_hash_find_combined(&map->hash, key, low, len);
  1703.     if (value) {
  1704.         return value;
  1705.     }

  1706. #if (NGX_PCRE)

  1707.     if (len && map->nregex) {
  1708.         ngx_int_t              n;
  1709.         ngx_uint_t             i;
  1710.         ngx_http_map_regex_t  *reg;

  1711.         reg = map->regex;

  1712.         for (i = 0; i < map->nregex; i++) {

  1713.             n = ngx_http_regex_exec(r, reg[i].regex, match);

  1714.             if (n == NGX_OK) {
  1715.                 return reg[i].value;
  1716.             }

  1717.             if (n == NGX_DECLINED) {
  1718.                 continue;
  1719.             }

  1720.             /* NGX_ERROR */

  1721.             return NULL;
  1722.         }
  1723.     }

  1724. #endif

  1725.     return NULL;
  1726. }


  1727. #if (NGX_PCRE)

  1728. static ngx_int_t
  1729. ngx_http_variable_not_found(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  1730.     uintptr_t data)
  1731. {
  1732.     v->not_found = 1;
  1733.     return NGX_OK;
  1734. }


  1735. ngx_http_regex_t *
  1736. ngx_http_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc)
  1737. {
  1738.     u_char                     *p;
  1739.     size_t                      size;
  1740.     ngx_str_t                   name;
  1741.     ngx_uint_t                  i, n;
  1742.     ngx_http_variable_t        *v;
  1743.     ngx_http_regex_t           *re;
  1744.     ngx_http_regex_variable_t  *rv;
  1745.     ngx_http_core_main_conf_t  *cmcf;

  1746.     rc->pool = cf->pool;

  1747.     if (ngx_regex_compile(rc) != NGX_OK) {
  1748.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err);
  1749.         return NULL;
  1750.     }

  1751.     re = ngx_pcalloc(cf->pool, sizeof(ngx_http_regex_t));
  1752.     if (re == NULL) {
  1753.         return NULL;
  1754.     }

  1755.     re->regex = rc->regex;
  1756.     re->ncaptures = rc->captures;
  1757.     re->name = rc->pattern;

  1758.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
  1759.     cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures);

  1760.     n = (ngx_uint_t) rc->named_captures;

  1761.     if (n == 0) {
  1762.         return re;
  1763.     }

  1764.     rv = ngx_palloc(rc->pool, n * sizeof(ngx_http_regex_variable_t));
  1765.     if (rv == NULL) {
  1766.         return NULL;
  1767.     }

  1768.     re->variables = rv;
  1769.     re->nvariables = n;

  1770.     size = rc->name_size;
  1771.     p = rc->names;

  1772.     for (i = 0; i < n; i++) {
  1773.         rv[i].capture = 2 * ((p[0] << 8) + p[1]);

  1774.         name.data = &p[2];
  1775.         name.len = ngx_strlen(name.data);

  1776.         v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
  1777.         if (v == NULL) {
  1778.             return NULL;
  1779.         }

  1780.         rv[i].index = ngx_http_get_variable_index(cf, &name);
  1781.         if (rv[i].index == NGX_ERROR) {
  1782.             return NULL;
  1783.         }

  1784.         v->get_handler = ngx_http_variable_not_found;

  1785.         p += size;
  1786.     }

  1787.     return re;
  1788. }


  1789. ngx_int_t
  1790. ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, ngx_str_t *s)
  1791. {
  1792.     ngx_int_t                   rc, index;
  1793.     ngx_uint_t                  i, n, len;
  1794.     ngx_http_variable_value_t  *vv;
  1795.     ngx_http_core_main_conf_t  *cmcf;

  1796.     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

  1797.     if (re->ncaptures) {
  1798.         len = cmcf->ncaptures;

  1799.         if (r->captures == NULL) {
  1800.             r->captures = ngx_palloc(r->pool, len * sizeof(int));
  1801.             if (r->captures == NULL) {
  1802.                 return NGX_ERROR;
  1803.             }
  1804.         }

  1805.     } else {
  1806.         len = 0;
  1807.     }

  1808.     rc = ngx_regex_exec(re->regex, s, r->captures, len);

  1809.     if (rc == NGX_REGEX_NO_MATCHED) {
  1810.         return NGX_DECLINED;
  1811.     }

  1812.     if (rc < 0) {
  1813.         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  1814.                       ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
  1815.                       rc, s, &re->name);
  1816.         return NGX_ERROR;
  1817.     }

  1818.     for (i = 0; i < re->nvariables; i++) {

  1819.         n = re->variables[i].capture;
  1820.         index = re->variables[i].index;
  1821.         vv = &r->variables[index];

  1822.         vv->len = r->captures[n + 1] - r->captures[n];
  1823.         vv->valid = 1;
  1824.         vv->no_cacheable = 0;
  1825.         vv->not_found = 0;
  1826.         vv->data = &s->data[r->captures[n]];

  1827. #if (NGX_DEBUG)
  1828.         {
  1829.         ngx_http_variable_t  *v;

  1830.         v = cmcf->variables.elts;

  1831.         ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  1832.                        "http regex set $%V to \"%*s\"",
  1833.                        &v[index].name, vv->len, vv->data);
  1834.         }
  1835. #endif
  1836.     }

  1837.     r->ncaptures = rc * 2;
  1838.     r->captures_data = s->data;

  1839.     return NGX_OK;
  1840. }

  1841. #endif


  1842. ngx_int_t
  1843. ngx_http_variables_add_core_vars(ngx_conf_t *cf)
  1844. {
  1845.     ngx_int_t                   rc;
  1846.     ngx_http_variable_t        *cv, *v;
  1847.     ngx_http_core_main_conf_t  *cmcf;

  1848.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

  1849.     cmcf->variables_keys = ngx_pcalloc(cf->temp_pool,
  1850.                                        sizeof(ngx_hash_keys_arrays_t));
  1851.     if (cmcf->variables_keys == NULL) {
  1852.         return NGX_ERROR;
  1853.     }

  1854.     cmcf->variables_keys->pool = cf->pool;
  1855.     cmcf->variables_keys->temp_pool = cf->pool;

  1856.     if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL)
  1857.         != NGX_OK)
  1858.     {
  1859.         return NGX_ERROR;
  1860.     }

  1861.     for (cv = ngx_http_core_variables; cv->name.len; cv++) {
  1862.         v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));
  1863.         if (v == NULL) {
  1864.             return NGX_ERROR;
  1865.         }

  1866.         *v = *cv;

  1867.         rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v,
  1868.                               NGX_HASH_READONLY_KEY);

  1869.         if (rc == NGX_OK) {
  1870.             continue;
  1871.         }

  1872.         if (rc == NGX_BUSY) {
  1873.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1874.                                "conflicting variable name \"%V\"", &v->name);
  1875.         }

  1876.         return NGX_ERROR;
  1877.     }

  1878.     return NGX_OK;
  1879. }


  1880. ngx_int_t
  1881. ngx_http_variables_init_vars(ngx_conf_t *cf)
  1882. {
  1883.     ngx_uint_t                  i, n;
  1884.     ngx_hash_key_t             *key;
  1885.     ngx_hash_init_t             hash;
  1886.     ngx_http_variable_t        *v, *av;
  1887.     ngx_http_core_main_conf_t  *cmcf;

  1888.     /* set the handlers for the indexed http variables */

  1889.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

  1890.     v = cmcf->variables.elts;
  1891.     key = cmcf->variables_keys->keys.elts;

  1892.     for (i = 0; i < cmcf->variables.nelts; i++) {

  1893.         for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {

  1894.             av = key[n].value;

  1895.             if (v[i].name.len == key[n].key.len
  1896.                 && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len)
  1897.                    == 0)
  1898.             {
  1899.                 v[i].get_handler = av->get_handler;
  1900.                 v[i].data = av->data;

  1901.                 av->flags |= NGX_HTTP_VAR_INDEXED;
  1902.                 v[i].flags = av->flags;

  1903.                 av->index = i;

  1904.                 if (av->get_handler == NULL) {
  1905.                     break;
  1906.                 }

  1907.                 goto next;
  1908.             }
  1909.         }

  1910.         if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) {
  1911.             v[i].get_handler = ngx_http_variable_unknown_header_in;
  1912.             v[i].data = (uintptr_t) &v[i].name;

  1913.             continue;
  1914.         }

  1915.         if (ngx_strncmp(v[i].name.data, "sent_http_", 10) == 0) {
  1916.             v[i].get_handler = ngx_http_variable_unknown_header_out;
  1917.             v[i].data = (uintptr_t) &v[i].name;

  1918.             continue;
  1919.         }

  1920.         if (ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0) {
  1921.             v[i].get_handler = ngx_http_upstream_header_variable;
  1922.             v[i].data = (uintptr_t) &v[i].name;
  1923.             v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;

  1924.             continue;
  1925.         }

  1926.         if (ngx_strncmp(v[i].name.data, "cookie_", 7) == 0) {
  1927.             v[i].get_handler = ngx_http_variable_cookie;
  1928.             v[i].data = (uintptr_t) &v[i].name;

  1929.             continue;
  1930.         }

  1931.         if (ngx_strncmp(v[i].name.data, "upstream_cookie_", 16) == 0) {
  1932.             v[i].get_handler = ngx_http_upstream_cookie_variable;
  1933.             v[i].data = (uintptr_t) &v[i].name;
  1934.             v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;

  1935.             continue;
  1936.         }

  1937.         if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) {
  1938.             v[i].get_handler = ngx_http_variable_argument;
  1939.             v[i].data = (uintptr_t) &v[i].name;
  1940.             v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;

  1941.             continue;
  1942.         }

  1943.         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  1944.                       "unknown \"%V\" variable", &v[i].name);

  1945.         return NGX_ERROR;

  1946.     next:
  1947.         continue;
  1948.     }


  1949.     for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {
  1950.         av = key[n].value;

  1951.         if (av->flags & NGX_HTTP_VAR_NOHASH) {
  1952.             key[n].key.data = NULL;
  1953.         }
  1954.     }


  1955.     hash.hash = &cmcf->variables_hash;
  1956.     hash.key = ngx_hash_key;
  1957.     hash.max_size = cmcf->variables_hash_max_size;
  1958.     hash.bucket_size = cmcf->variables_hash_bucket_size;
  1959.     hash.name = "variables_hash";
  1960.     hash.pool = cf->pool;
  1961.     hash.temp_pool = NULL;

  1962.     if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts,
  1963.                       cmcf->variables_keys->keys.nelts)
  1964.         != NGX_OK)
  1965.     {
  1966.         return NGX_ERROR;
  1967.     }

  1968.     cmcf->variables_keys = NULL;

  1969.     return NGX_OK;
  1970. }