src/http/ngx_http_variables.c - nginx source code

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_http_variable_t *ngx_http_add_prefix_variable(ngx_conf_t *cf,
  10.     ngx_str_t *name, ngx_uint_t flags);

  11. static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r,
  12.     ngx_http_variable_value_t *v, uintptr_t data);
  13. #if 0
  14. static void ngx_http_variable_request_set(ngx_http_request_t *r,
  15.     ngx_http_variable_value_t *v, uintptr_t data);
  16. #endif
  17. static ngx_int_t ngx_http_variable_request_get_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_internal(ngx_http_request_t *r,
  24.     ngx_http_variable_value_t *v, uintptr_t data, u_char sep);

  25. static ngx_int_t ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
  26.     ngx_http_variable_value_t *v, uintptr_t data);
  27. static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
  28.     ngx_http_variable_value_t *v, uintptr_t data);
  29. static ngx_int_t ngx_http_variable_unknown_trailer_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_proxy_protocol_port(ngx_http_request_t *r,
  54.     ngx_http_variable_value_t *v, uintptr_t data);
  55. static ngx_int_t ngx_http_variable_proxy_protocol_tlv(ngx_http_request_t *r,
  56.     ngx_http_variable_value_t *v, uintptr_t data);
  57. static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r,
  58.     ngx_http_variable_value_t *v, uintptr_t data);
  59. static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
  60.     ngx_http_variable_value_t *v, uintptr_t data);
  61. static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r,
  62.     ngx_http_variable_value_t *v, uintptr_t data);
  63. static ngx_int_t ngx_http_variable_https(ngx_http_request_t *r,
  64.     ngx_http_variable_value_t *v, uintptr_t data);
  65. static void ngx_http_variable_set_args(ngx_http_request_t *r,
  66.     ngx_http_variable_value_t *v, uintptr_t data);
  67. static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r,
  68.     ngx_http_variable_value_t *v, uintptr_t data);
  69. static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r,
  70.     ngx_http_variable_value_t *v, uintptr_t data);
  71. static ngx_int_t ngx_http_variable_realpath_root(ngx_http_request_t *r,
  72.     ngx_http_variable_value_t *v, uintptr_t data);
  73. static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r,
  74.     ngx_http_variable_value_t *v, uintptr_t data);
  75. static ngx_int_t ngx_http_variable_server_name(ngx_http_request_t *r,
  76.     ngx_http_variable_value_t *v, uintptr_t data);
  77. static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r,
  78.     ngx_http_variable_value_t *v, uintptr_t data);
  79. static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r,
  80.     ngx_http_variable_value_t *v, uintptr_t data);
  81. static ngx_int_t ngx_http_variable_bytes_sent(ngx_http_request_t *r,
  82.     ngx_http_variable_value_t *v, uintptr_t data);
  83. static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
  84.     ngx_http_variable_value_t *v, uintptr_t data);
  85. static ngx_int_t ngx_http_variable_pipe(ngx_http_request_t *r,
  86.     ngx_http_variable_value_t *v, uintptr_t data);
  87. static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
  88.     ngx_http_variable_value_t *v, uintptr_t data);
  89. static ngx_int_t ngx_http_variable_request_body(ngx_http_request_t *r,
  90.     ngx_http_variable_value_t *v, uintptr_t data);
  91. static ngx_int_t ngx_http_variable_request_body_file(ngx_http_request_t *r,
  92.     ngx_http_variable_value_t *v, uintptr_t data);
  93. static ngx_int_t ngx_http_variable_request_length(ngx_http_request_t *r,
  94.     ngx_http_variable_value_t *v, uintptr_t data);
  95. static ngx_int_t ngx_http_variable_request_time(ngx_http_request_t *r,
  96.     ngx_http_variable_value_t *v, uintptr_t data);
  97. static ngx_int_t ngx_http_variable_request_id(ngx_http_request_t *r,
  98.     ngx_http_variable_value_t *v, uintptr_t data);
  99. static ngx_int_t ngx_http_variable_status(ngx_http_request_t *r,
  100.     ngx_http_variable_value_t *v, uintptr_t data);

  101. static ngx_int_t ngx_http_variable_sent_content_type(ngx_http_request_t *r,
  102.     ngx_http_variable_value_t *v, uintptr_t data);
  103. static ngx_int_t ngx_http_variable_sent_content_length(ngx_http_request_t *r,
  104.     ngx_http_variable_value_t *v, uintptr_t data);
  105. static ngx_int_t ngx_http_variable_sent_location(ngx_http_request_t *r,
  106.     ngx_http_variable_value_t *v, uintptr_t data);
  107. static ngx_int_t ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
  108.     ngx_http_variable_value_t *v, uintptr_t data);
  109. static ngx_int_t ngx_http_variable_sent_connection(ngx_http_request_t *r,
  110.     ngx_http_variable_value_t *v, uintptr_t data);
  111. static ngx_int_t ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
  112.     ngx_http_variable_value_t *v, uintptr_t data);
  113. static ngx_int_t ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
  114.     ngx_http_variable_value_t *v, uintptr_t data);
  115. static void ngx_http_variable_set_limit_rate(ngx_http_request_t *r,
  116.     ngx_http_variable_value_t *v, uintptr_t data);

  117. static ngx_int_t ngx_http_variable_connection(ngx_http_request_t *r,
  118.     ngx_http_variable_value_t *v, uintptr_t data);
  119. static ngx_int_t ngx_http_variable_connection_requests(ngx_http_request_t *r,
  120.     ngx_http_variable_value_t *v, uintptr_t data);
  121. static ngx_int_t ngx_http_variable_connection_time(ngx_http_request_t *r,
  122.     ngx_http_variable_value_t *v, uintptr_t data);

  123. static ngx_int_t ngx_http_variable_nginx_version(ngx_http_request_t *r,
  124.     ngx_http_variable_value_t *v, uintptr_t data);
  125. static ngx_int_t ngx_http_variable_hostname(ngx_http_request_t *r,
  126.     ngx_http_variable_value_t *v, uintptr_t data);
  127. static ngx_int_t ngx_http_variable_pid(ngx_http_request_t *r,
  128.     ngx_http_variable_value_t *v, uintptr_t data);
  129. static ngx_int_t ngx_http_variable_msec(ngx_http_request_t *r,
  130.     ngx_http_variable_value_t *v, uintptr_t data);
  131. static ngx_int_t ngx_http_variable_time_iso8601(ngx_http_request_t *r,
  132.     ngx_http_variable_value_t *v, uintptr_t data);
  133. static ngx_int_t ngx_http_variable_time_local(ngx_http_request_t *r,
  134.     ngx_http_variable_value_t *v, uintptr_t data);

  135. /*
  136. * TODO:
  137. *     Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED
  138. *                 REMOTE_HOST (null), REMOTE_IDENT (null),
  139. *                 SERVER_SOFTWARE
  140. *
  141. *     Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner)
  142. */

  143. /*
  144. * the $http_host, $http_user_agent, $http_referer, and $http_via
  145. * variables may be handled by generic
  146. * ngx_http_variable_unknown_header_in(), but for performance reasons
  147. * they are handled using dedicated entries
  148. */

  149. static ngx_http_variable_t  ngx_http_core_variables[] = {

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

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

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

  156. #if (NGX_HTTP_GZIP)
  157.     { ngx_string("http_via"), NULL, ngx_http_variable_header,
  158.       offsetof(ngx_http_request_t, headers_in.via), 0, 0 },
  159. #endif

  160. #if (NGX_HTTP_X_FORWARDED_FOR)
  161.     { ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_header,
  162.       offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 },
  163. #endif

  164.     { ngx_string("http_cookie"), NULL, ngx_http_variable_cookies,
  165.       offsetof(ngx_http_request_t, headers_in.cookie), 0, 0 },

  166.     { ngx_string("content_length"), NULL, ngx_http_variable_content_length,
  167.       0, 0, 0 },

  168.     { ngx_string("content_type"), NULL, ngx_http_variable_header,
  169.       offsetof(ngx_http_request_t, headers_in.content_type), 0, 0 },

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

  171.     { ngx_string("binary_remote_addr"), NULL,
  172.       ngx_http_variable_binary_remote_addr, 0, 0, 0 },

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

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

  175.     { ngx_string("proxy_protocol_addr"), NULL,
  176.       ngx_http_variable_proxy_protocol_addr,
  177.       offsetof(ngx_proxy_protocol_t, src_addr), 0, 0 },

  178.     { ngx_string("proxy_protocol_port"), NULL,
  179.       ngx_http_variable_proxy_protocol_port,
  180.       offsetof(ngx_proxy_protocol_t, src_port), 0, 0 },

  181.     { ngx_string("proxy_protocol_server_addr"), NULL,
  182.       ngx_http_variable_proxy_protocol_addr,
  183.       offsetof(ngx_proxy_protocol_t, dst_addr), 0, 0 },

  184.     { ngx_string("proxy_protocol_server_port"), NULL,
  185.       ngx_http_variable_proxy_protocol_port,
  186.       offsetof(ngx_proxy_protocol_t, dst_port), 0, 0 },

  187.     { ngx_string("proxy_protocol_tlv_"), NULL,
  188.       ngx_http_variable_proxy_protocol_tlv,
  189.       0, NGX_HTTP_VAR_PREFIX, 0 },

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

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

  192.     { ngx_string("server_protocol"), NULL, ngx_http_variable_request,
  193.       offsetof(ngx_http_request_t, http_protocol), 0, 0 },

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

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

  196.     { ngx_string("request_uri"), NULL, ngx_http_variable_request,
  197.       offsetof(ngx_http_request_t, unparsed_uri), 0, 0 },

  198.     { ngx_string("uri"), NULL, ngx_http_variable_request,
  199.       offsetof(ngx_http_request_t, uri),
  200.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  201.     { ngx_string("document_uri"), NULL, ngx_http_variable_request,
  202.       offsetof(ngx_http_request_t, uri),
  203.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

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

  205.     { ngx_string("document_root"), NULL,
  206.       ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  207.     { ngx_string("realpath_root"), NULL,
  208.       ngx_http_variable_realpath_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  209.     { ngx_string("query_string"), NULL, ngx_http_variable_request,
  210.       offsetof(ngx_http_request_t, args),
  211.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  212.     { ngx_string("args"),
  213.       ngx_http_variable_set_args,
  214.       ngx_http_variable_request,
  215.       offsetof(ngx_http_request_t, args),
  216.       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },

  217.     { ngx_string("is_args"), NULL, ngx_http_variable_is_args,
  218.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  219.     { ngx_string("request_filename"), NULL,
  220.       ngx_http_variable_request_filename, 0,
  221.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

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

  223.     { ngx_string("request_method"), NULL,
  224.       ngx_http_variable_request_method, 0,
  225.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

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

  227.     { ngx_string("bytes_sent"), NULL, ngx_http_variable_bytes_sent,
  228.       0, 0, 0 },

  229.     { ngx_string("body_bytes_sent"), NULL, ngx_http_variable_body_bytes_sent,
  230.       0, 0, 0 },

  231.     { ngx_string("pipe"), NULL, ngx_http_variable_pipe,
  232.       0, 0, 0 },

  233.     { ngx_string("request_completion"), NULL,
  234.       ngx_http_variable_request_completion,
  235.       0, 0, 0 },

  236.     { ngx_string("request_body"), NULL,
  237.       ngx_http_variable_request_body,
  238.       0, 0, 0 },

  239.     { ngx_string("request_body_file"), NULL,
  240.       ngx_http_variable_request_body_file,
  241.       0, 0, 0 },

  242.     { ngx_string("request_length"), NULL, ngx_http_variable_request_length,
  243.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  244.     { ngx_string("request_time"), NULL, ngx_http_variable_request_time,
  245.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  246.     { ngx_string("request_id"), NULL,
  247.       ngx_http_variable_request_id,
  248.       0, 0, 0 },

  249.     { ngx_string("status"), NULL,
  250.       ngx_http_variable_status, 0,
  251.       NGX_HTTP_VAR_NOCACHEABLE, 0 },

  252.     { ngx_string("sent_http_content_type"), NULL,
  253.       ngx_http_variable_sent_content_type, 0, 0, 0 },

  254.     { ngx_string("sent_http_content_length"), NULL,
  255.       ngx_http_variable_sent_content_length, 0, 0, 0 },

  256.     { ngx_string("sent_http_location"), NULL,
  257.       ngx_http_variable_sent_location, 0, 0, 0 },

  258.     { ngx_string("sent_http_last_modified"), NULL,
  259.       ngx_http_variable_sent_last_modified, 0, 0, 0 },

  260.     { ngx_string("sent_http_connection"), NULL,
  261.       ngx_http_variable_sent_connection, 0, 0, 0 },

  262.     { ngx_string("sent_http_keep_alive"), NULL,
  263.       ngx_http_variable_sent_keep_alive, 0, 0, 0 },

  264.     { ngx_string("sent_http_transfer_encoding"), NULL,
  265.       ngx_http_variable_sent_transfer_encoding, 0, 0, 0 },

  266.     { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_header,
  267.       offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 },

  268.     { ngx_string("sent_http_link"), NULL, ngx_http_variable_header,
  269.       offsetof(ngx_http_request_t, headers_out.link), 0, 0 },

  270.     { ngx_string("limit_rate"), ngx_http_variable_set_limit_rate,
  271.       ngx_http_variable_request_get_size,
  272.       offsetof(ngx_http_request_t, limit_rate),
  273.       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },

  274.     { ngx_string("connection"), NULL,
  275.       ngx_http_variable_connection, 0, 0, 0 },

  276.     { ngx_string("connection_requests"), NULL,
  277.       ngx_http_variable_connection_requests, 0, 0, 0 },

  278.     { ngx_string("connection_time"), NULL, ngx_http_variable_connection_time,
  279.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  280.     { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version,
  281.       0, 0, 0 },

  282.     { ngx_string("hostname"), NULL, ngx_http_variable_hostname,
  283.       0, 0, 0 },

  284.     { ngx_string("pid"), NULL, ngx_http_variable_pid,
  285.       0, 0, 0 },

  286.     { ngx_string("msec"), NULL, ngx_http_variable_msec,
  287.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  288.     { ngx_string("time_iso8601"), NULL, ngx_http_variable_time_iso8601,
  289.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  290.     { ngx_string("time_local"), NULL, ngx_http_variable_time_local,
  291.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  292. #if (NGX_HAVE_TCP_INFO)
  293.     { ngx_string("tcpinfo_rtt"), NULL, ngx_http_variable_tcpinfo,
  294.       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  295.     { ngx_string("tcpinfo_rttvar"), NULL, ngx_http_variable_tcpinfo,
  296.       1, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  297.     { ngx_string("tcpinfo_snd_cwnd"), NULL, ngx_http_variable_tcpinfo,
  298.       2, NGX_HTTP_VAR_NOCACHEABLE, 0 },

  299.     { ngx_string("tcpinfo_rcv_space"), NULL, ngx_http_variable_tcpinfo,
  300.       3, NGX_HTTP_VAR_NOCACHEABLE, 0 },
  301. #endif

  302.     { ngx_string("http_"), NULL, ngx_http_variable_unknown_header_in,
  303.       0, NGX_HTTP_VAR_PREFIX, 0 },

  304.     { ngx_string("sent_http_"), NULL, ngx_http_variable_unknown_header_out,
  305.       0, NGX_HTTP_VAR_PREFIX, 0 },

  306.     { ngx_string("sent_trailer_"), NULL, ngx_http_variable_unknown_trailer_out,
  307.       0, NGX_HTTP_VAR_PREFIX, 0 },

  308.     { ngx_string("cookie_"), NULL, ngx_http_variable_cookie,
  309.       0, NGX_HTTP_VAR_PREFIX, 0 },

  310.     { ngx_string("arg_"), NULL, ngx_http_variable_argument,
  311.       0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 },

  312.       ngx_http_null_variable
  313. };


  314. ngx_http_variable_value_t  ngx_http_variable_null_value =
  315.     ngx_http_variable("");
  316. ngx_http_variable_value_t  ngx_http_variable_true_value =
  317.     ngx_http_variable("1");


  318. static ngx_uint_t  ngx_http_variable_depth = 100;


  319. ngx_http_variable_t *
  320. ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
  321. {
  322.     ngx_int_t                   rc;
  323.     ngx_uint_t                  i;
  324.     ngx_hash_key_t             *key;
  325.     ngx_http_variable_t        *v;
  326.     ngx_http_core_main_conf_t  *cmcf;

  327.     if (name->len == 0) {
  328.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  329.                            "invalid variable name \"$\"");
  330.         return NULL;
  331.     }

  332.     if (flags & NGX_HTTP_VAR_PREFIX) {
  333.         return ngx_http_add_prefix_variable(cf, name, flags);
  334.     }

  335.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

  336.     key = cmcf->variables_keys->keys.elts;
  337.     for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) {
  338.         if (name->len != key[i].key.len
  339.             || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0)
  340.         {
  341.             continue;
  342.         }

  343.         v = key[i].value;

  344.         if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
  345.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  346.                                "the duplicate \"%V\" variable", name);
  347.             return NULL;
  348.         }

  349.         if (!(flags & NGX_HTTP_VAR_WEAK)) {
  350.             v->flags &= ~NGX_HTTP_VAR_WEAK;
  351.         }

  352.         return v;
  353.     }

  354.     v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));
  355.     if (v == NULL) {
  356.         return NULL;
  357.     }

  358.     v->name.len = name->len;
  359.     v->name.data = ngx_pnalloc(cf->pool, name->len);
  360.     if (v->name.data == NULL) {
  361.         return NULL;
  362.     }

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

  364.     v->set_handler = NULL;
  365.     v->get_handler = NULL;
  366.     v->data = 0;
  367.     v->flags = flags;
  368.     v->index = 0;

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

  370.     if (rc == NGX_ERROR) {
  371.         return NULL;
  372.     }

  373.     if (rc == NGX_BUSY) {
  374.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  375.                            "conflicting variable name \"%V\"", name);
  376.         return NULL;
  377.     }

  378.     return v;
  379. }


  380. static ngx_http_variable_t *
  381. ngx_http_add_prefix_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
  382. {
  383.     ngx_uint_t                  i;
  384.     ngx_http_variable_t        *v;
  385.     ngx_http_core_main_conf_t  *cmcf;

  386.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

  387.     v = cmcf->prefix_variables.elts;
  388.     for (i = 0; i < cmcf->prefix_variables.nelts; i++) {
  389.         if (name->len != v[i].name.len
  390.             || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0)
  391.         {
  392.             continue;
  393.         }

  394.         v = &v[i];

  395.         if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
  396.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  397.                                "the duplicate \"%V\" variable", name);
  398.             return NULL;
  399.         }

  400.         if (!(flags & NGX_HTTP_VAR_WEAK)) {
  401.             v->flags &= ~NGX_HTTP_VAR_WEAK;
  402.         }

  403.         return v;
  404.     }

  405.     v = ngx_array_push(&cmcf->prefix_variables);
  406.     if (v == NULL) {
  407.         return NULL;
  408.     }

  409.     v->name.len = name->len;
  410.     v->name.data = ngx_pnalloc(cf->pool, name->len);
  411.     if (v->name.data == NULL) {
  412.         return NULL;
  413.     }

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

  415.     v->set_handler = NULL;
  416.     v->get_handler = NULL;
  417.     v->data = 0;
  418.     v->flags = flags;
  419.     v->index = 0;

  420.     return v;
  421. }


  422. ngx_int_t
  423. ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name)
  424. {
  425.     ngx_uint_t                  i;
  426.     ngx_http_variable_t        *v;
  427.     ngx_http_core_main_conf_t  *cmcf;

  428.     if (name->len == 0) {
  429.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  430.                            "invalid variable name \"$\"");
  431.         return NGX_ERROR;
  432.     }

  433.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

  434.     v = cmcf->variables.elts;

  435.     if (v == NULL) {
  436.         if (ngx_array_init(&cmcf->variables, cf->pool, 4,
  437.                            sizeof(ngx_http_variable_t))
  438.             != NGX_OK)
  439.         {
  440.             return NGX_ERROR;
  441.         }

  442.     } else {
  443.         for (i = 0; i < cmcf->variables.nelts; i++) {
  444.             if (name->len != v[i].name.len
  445.                 || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0)
  446.             {
  447.                 continue;
  448.             }

  449.             return i;
  450.         }
  451.     }

  452.     v = ngx_array_push(&cmcf->variables);
  453.     if (v == NULL) {
  454.         return NGX_ERROR;
  455.     }

  456.     v->name.len = name->len;
  457.     v->name.data = ngx_pnalloc(cf->pool, name->len);
  458.     if (v->name.data == NULL) {
  459.         return NGX_ERROR;
  460.     }

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

  462.     v->set_handler = NULL;
  463.     v->get_handler = NULL;
  464.     v->data = 0;
  465.     v->flags = 0;
  466.     v->index = cmcf->variables.nelts - 1;

  467.     return v->index;
  468. }


  469. ngx_http_variable_value_t *
  470. ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
  471. {
  472.     ngx_http_variable_t        *v;
  473.     ngx_http_core_main_conf_t  *cmcf;

  474.     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

  475.     if (cmcf->variables.nelts <= index) {
  476.         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  477.                       "unknown variable index: %ui", index);
  478.         return NULL;
  479.     }

  480.     if (r->variables[index].not_found || r->variables[index].valid) {
  481.         return &r->variables[index];
  482.     }

  483.     v = cmcf->variables.elts;

  484.     if (ngx_http_variable_depth == 0) {
  485.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  486.                       "cycle while evaluating variable \"%V\"",
  487.                       &v[index].name);
  488.         return NULL;
  489.     }

  490.     ngx_http_variable_depth--;

  491.     if (v[index].get_handler(r, &r->variables[index], v[index].data)
  492.         == NGX_OK)
  493.     {
  494.         ngx_http_variable_depth++;

  495.         if (v[index].flags & NGX_HTTP_VAR_NOCACHEABLE) {
  496.             r->variables[index].no_cacheable = 1;
  497.         }

  498.         return &r->variables[index];
  499.     }

  500.     ngx_http_variable_depth++;

  501.     r->variables[index].valid = 0;
  502.     r->variables[index].not_found = 1;

  503.     return NULL;
  504. }


  505. ngx_http_variable_value_t *
  506. ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index)
  507. {
  508.     ngx_http_variable_value_t  *v;

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

  510.     if (v->valid || v->not_found) {
  511.         if (!v->no_cacheable) {
  512.             return v;
  513.         }

  514.         v->valid = 0;
  515.         v->not_found = 0;
  516.     }

  517.     return ngx_http_get_indexed_variable(r, index);
  518. }


  519. ngx_http_variable_value_t *
  520. ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
  521. {
  522.     size_t                      len;
  523.     ngx_uint_t                  i, n;
  524.     ngx_http_variable_t        *v;
  525.     ngx_http_variable_value_t  *vv;
  526.     ngx_http_core_main_conf_t  *cmcf;

  527.     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

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

  529.     if (v) {
  530.         if (v->flags & NGX_HTTP_VAR_INDEXED) {
  531.             return ngx_http_get_flushed_variable(r, v->index);
  532.         }

  533.         if (ngx_http_variable_depth == 0) {
  534.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  535.                           "cycle while evaluating variable \"%V\"", name);
  536.             return NULL;
  537.         }

  538.         ngx_http_variable_depth--;

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

  540.         if (vv && v->get_handler(r, vv, v->data) == NGX_OK) {
  541.             ngx_http_variable_depth++;
  542.             return vv;
  543.         }

  544.         ngx_http_variable_depth++;
  545.         return NULL;
  546.     }

  547.     vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
  548.     if (vv == NULL) {
  549.         return NULL;
  550.     }

  551.     len = 0;

  552.     v = cmcf->prefix_variables.elts;
  553.     n = cmcf->prefix_variables.nelts;

  554.     for (i = 0; i < cmcf->prefix_variables.nelts; i++) {
  555.         if (name->len >= v[i].name.len && name->len > len
  556.             && ngx_strncmp(name->data, v[i].name.data, v[i].name.len) == 0)
  557.         {
  558.             len = v[i].name.len;
  559.             n = i;
  560.         }
  561.     }

  562.     if (n != cmcf->prefix_variables.nelts) {
  563.         if (v[n].get_handler(r, vv, (uintptr_t) name) == NGX_OK) {
  564.             return vv;
  565.         }

  566.         return NULL;
  567.     }

  568.     vv->not_found = 1;

  569.     return vv;
  570. }


  571. static ngx_int_t
  572. ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  573.     uintptr_t data)
  574. {
  575.     ngx_str_t  *s;

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

  577.     if (s->data) {
  578.         v->len = s->len;
  579.         v->valid = 1;
  580.         v->no_cacheable = 0;
  581.         v->not_found = 0;
  582.         v->data = s->data;

  583.     } else {
  584.         v->not_found = 1;
  585.     }

  586.     return NGX_OK;
  587. }


  588. #if 0

  589. static void
  590. ngx_http_variable_request_set(ngx_http_request_t *r,
  591.     ngx_http_variable_value_t *v, uintptr_t data)
  592. {
  593.     ngx_str_t  *s;

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

  595.     s->len = v->len;
  596.     s->data = v->data;
  597. }

  598. #endif


  599. static ngx_int_t
  600. ngx_http_variable_request_get_size(ngx_http_request_t *r,
  601.     ngx_http_variable_value_t *v, uintptr_t data)
  602. {
  603.     size_t  *sp;

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

  605.     v->data = ngx_pnalloc(r->pool, NGX_SIZE_T_LEN);
  606.     if (v->data == NULL) {
  607.         return NGX_ERROR;
  608.     }

  609.     v->len = ngx_sprintf(v->data, "%uz", *sp) - v->data;
  610.     v->valid = 1;
  611.     v->no_cacheable = 0;
  612.     v->not_found = 0;

  613.     return NGX_OK;
  614. }


  615. static ngx_int_t
  616. ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  617.     uintptr_t data)
  618. {
  619.     return ngx_http_variable_headers_internal(r, v, data, ',');
  620. }


  621. static ngx_int_t
  622. ngx_http_variable_cookies(ngx_http_request_t *r,
  623.     ngx_http_variable_value_t *v, uintptr_t data)
  624. {
  625.     return ngx_http_variable_headers_internal(r, v, data, ';');
  626. }


  627. static ngx_int_t
  628. ngx_http_variable_headers_internal(ngx_http_request_t *r,
  629.     ngx_http_variable_value_t *v, uintptr_t data, u_char sep)
  630. {
  631.     size_t            len;
  632.     u_char           *p, *end;
  633.     ngx_table_elt_t  *h, *th;

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

  635.     len = 0;

  636.     for (th = h; th; th = th->next) {

  637.         if (th->hash == 0) {
  638.             continue;
  639.         }

  640.         len += th->value.len + 2;
  641.     }

  642.     if (len == 0) {
  643.         v->not_found = 1;
  644.         return NGX_OK;
  645.     }

  646.     len -= 2;

  647.     v->valid = 1;
  648.     v->no_cacheable = 0;
  649.     v->not_found = 0;

  650.     if (h->next == NULL) {
  651.         v->len = h->value.len;
  652.         v->data = h->value.data;

  653.         return NGX_OK;
  654.     }

  655.     p = ngx_pnalloc(r->pool, len);
  656.     if (p == NULL) {
  657.         return NGX_ERROR;
  658.     }

  659.     v->len = len;
  660.     v->data = p;

  661.     end = p + len;

  662.     for (th = h; th; th = th->next) {

  663.         if (th->hash == 0) {
  664.             continue;
  665.         }

  666.         p = ngx_copy(p, th->value.data, th->value.len);

  667.         if (p == end) {
  668.             break;
  669.         }

  670.         *p++ = sep; *p++ = ' ';
  671.     }

  672.     return NGX_OK;
  673. }


  674. static ngx_int_t
  675. ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
  676.     ngx_http_variable_value_t *v, uintptr_t data)
  677. {
  678.     return ngx_http_variable_unknown_header(r, v, (ngx_str_t *) data,
  679.                                             &r->headers_in.headers.part,
  680.                                             sizeof("http_") - 1);
  681. }


  682. static ngx_int_t
  683. ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
  684.     ngx_http_variable_value_t *v, uintptr_t data)
  685. {
  686.     return ngx_http_variable_unknown_header(r, v, (ngx_str_t *) data,
  687.                                             &r->headers_out.headers.part,
  688.                                             sizeof("sent_http_") - 1);
  689. }


  690. static ngx_int_t
  691. ngx_http_variable_unknown_trailer_out(ngx_http_request_t *r,
  692.     ngx_http_variable_value_t *v, uintptr_t data)
  693. {
  694.     return ngx_http_variable_unknown_header(r, v, (ngx_str_t *) data,
  695.                                             &r->headers_out.trailers.part,
  696.                                             sizeof("sent_trailer_") - 1);
  697. }


  698. ngx_int_t
  699. ngx_http_variable_unknown_header(ngx_http_request_t *r,
  700.     ngx_http_variable_value_t *v, ngx_str_t *var,
  701.     ngx_list_part_t *part, size_t prefix)
  702. {
  703.     u_char           *p, ch;
  704.     size_t            len;
  705.     ngx_uint_t        i, n;
  706.     ngx_table_elt_t  *header, *h, **ph;

  707.     ph = &h;
  708. #if (NGX_SUPPRESS_WARN)
  709.     len = 0;
  710. #endif

  711.     header = part->elts;

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

  713.         if (i >= part->nelts) {
  714.             if (part->next == NULL) {
  715.                 break;
  716.             }

  717.             part = part->next;
  718.             header = part->elts;
  719.             i = 0;
  720.         }

  721.         if (header[i].hash == 0) {
  722.             continue;
  723.         }

  724.         if (header[i].key.len != var->len - prefix) {
  725.             continue;
  726.         }

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

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

  731.             } else if (ch == '-') {
  732.                 ch = '_';
  733.             }

  734.             if (var->data[n + prefix] != ch) {
  735.                 break;
  736.             }
  737.         }

  738.         if (n != var->len - prefix) {
  739.             continue;
  740.         }

  741.         len += header[i].value.len + 2;

  742.         *ph = &header[i];
  743.         ph = &header[i].next;
  744.     }

  745.     *ph = NULL;

  746.     if (h == NULL) {
  747.         v->not_found = 1;
  748.         return NGX_OK;
  749.     }

  750.     len -= 2;

  751.     if (h->next == NULL) {

  752.         v->len = h->value.len;
  753.         v->valid = 1;
  754.         v->no_cacheable = 0;
  755.         v->not_found = 0;
  756.         v->data = h->value.data;

  757.         return NGX_OK;
  758.     }

  759.     p = ngx_pnalloc(r->pool, len);
  760.     if (p == NULL) {
  761.         return NGX_ERROR;
  762.     }

  763.     v->len = len;
  764.     v->valid = 1;
  765.     v->no_cacheable = 0;
  766.     v->not_found = 0;
  767.     v->data = p;

  768.     for ( ;; ) {

  769.         p = ngx_copy(p, h->value.data, h->value.len);

  770.         if (h->next == NULL) {
  771.             break;
  772.         }

  773.         *p++ = ','; *p++ = ' ';

  774.         h = h->next;
  775.     }

  776.     return NGX_OK;
  777. }


  778. static ngx_int_t
  779. ngx_http_variable_request_line(ngx_http_request_t *r,
  780.     ngx_http_variable_value_t *v, uintptr_t data)
  781. {
  782.     u_char  *p, *s;

  783.     s = r->request_line.data;

  784.     if (s == NULL) {
  785.         s = r->request_start;

  786.         if (s == NULL) {
  787.             v->not_found = 1;
  788.             return NGX_OK;
  789.         }

  790.         for (p = s; p < r->header_in->last; p++) {
  791.             if (*p == CR || *p == LF) {
  792.                 break;
  793.             }
  794.         }

  795.         r->request_line.len = p - s;
  796.         r->request_line.data = s;
  797.     }

  798.     v->len = r->request_line.len;
  799.     v->valid = 1;
  800.     v->no_cacheable = 0;
  801.     v->not_found = 0;
  802.     v->data = s;

  803.     return NGX_OK;
  804. }


  805. static ngx_int_t
  806. ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  807.     uintptr_t data)
  808. {
  809.     ngx_str_t *name = (ngx_str_t *) data;

  810.     ngx_str_t  cookie, s;

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

  813.     if (ngx_http_parse_multi_header_lines(r, r->headers_in.cookie, &s, &cookie)
  814.         == NULL)
  815.     {
  816.         v->not_found = 1;
  817.         return NGX_OK;
  818.     }

  819.     v->len = cookie.len;
  820.     v->valid = 1;
  821.     v->no_cacheable = 0;
  822.     v->not_found = 0;
  823.     v->data = cookie.data;

  824.     return NGX_OK;
  825. }


  826. static ngx_int_t
  827. ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  828.     uintptr_t data)
  829. {
  830.     ngx_str_t *name = (ngx_str_t *) data;

  831.     u_char     *arg;
  832.     size_t      len;
  833.     ngx_str_t   value;

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

  836.     if (len == 0 || ngx_http_arg(r, arg, len, &value) != NGX_OK) {
  837.         v->not_found = 1;
  838.         return NGX_OK;
  839.     }

  840.     v->data = value.data;
  841.     v->len = value.len;
  842.     v->valid = 1;
  843.     v->no_cacheable = 0;
  844.     v->not_found = 0;

  845.     return NGX_OK;
  846. }


  847. #if (NGX_HAVE_TCP_INFO)

  848. static ngx_int_t
  849. ngx_http_variable_tcpinfo(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  850.     uintptr_t data)
  851. {
  852.     struct tcp_info  ti;
  853.     socklen_t        len;
  854.     uint32_t         value;

  855.     len = sizeof(struct tcp_info);
  856.     if (getsockopt(r->connection->fd, IPPROTO_TCP, TCP_INFO, &ti, &len) == -1) {
  857.         v->not_found = 1;
  858.         return NGX_OK;
  859.     }

  860.     v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN);
  861.     if (v->data == NULL) {
  862.         return NGX_ERROR;
  863.     }

  864.     switch (data) {
  865.     case 0:
  866.         value = ti.tcpi_rtt;
  867.         break;

  868.     case 1:
  869.         value = ti.tcpi_rttvar;
  870.         break;

  871.     case 2:
  872.         value = ti.tcpi_snd_cwnd;
  873.         break;

  874.     case 3:
  875.         value = ti.tcpi_rcv_space;
  876.         break;

  877.     /* suppress warning */
  878.     default:
  879.         value = 0;
  880.         break;
  881.     }

  882.     v->len = ngx_sprintf(v->data, "%uD", value) - v->data;
  883.     v->valid = 1;
  884.     v->no_cacheable = 0;
  885.     v->not_found = 0;

  886.     return NGX_OK;
  887. }

  888. #endif


  889. static ngx_int_t
  890. ngx_http_variable_content_length(ngx_http_request_t *r,
  891.     ngx_http_variable_value_t *v, uintptr_t data)
  892. {
  893.     u_char  *p;

  894.     if (r->headers_in.content_length) {
  895.         v->len = r->headers_in.content_length->value.len;
  896.         v->data = r->headers_in.content_length->value.data;
  897.         v->valid = 1;
  898.         v->no_cacheable = 0;
  899.         v->not_found = 0;

  900.     } else if (r->reading_body) {
  901.         v->not_found = 1;
  902.         v->no_cacheable = 1;

  903.     } else if (r->headers_in.content_length_n >= 0) {
  904.         p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
  905.         if (p == NULL) {
  906.             return NGX_ERROR;
  907.         }

  908.         v->len = ngx_sprintf(p, "%O", r->headers_in.content_length_n) - p;
  909.         v->data = p;
  910.         v->valid = 1;
  911.         v->no_cacheable = 0;
  912.         v->not_found = 0;

  913.     } else if (r->headers_in.chunked) {
  914.         v->not_found = 1;
  915.         v->no_cacheable = 1;

  916.     } else {
  917.         v->not_found = 1;
  918.     }

  919.     return NGX_OK;
  920. }


  921. static ngx_int_t
  922. ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  923.     uintptr_t data)
  924. {
  925.     ngx_http_core_srv_conf_t  *cscf;

  926.     if (r->headers_in.server.len) {
  927.         v->len = r->headers_in.server.len;
  928.         v->data = r->headers_in.server.data;

  929.     } else {
  930.         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);

  931.         v->len = cscf->server_name.len;
  932.         v->data = cscf->server_name.data;
  933.     }

  934.     v->valid = 1;
  935.     v->no_cacheable = 0;
  936.     v->not_found = 0;

  937.     return NGX_OK;
  938. }


  939. static ngx_int_t
  940. ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
  941.     ngx_http_variable_value_t *v, uintptr_t data)
  942. {
  943.     struct sockaddr_in   *sin;
  944. #if (NGX_HAVE_INET6)
  945.     struct sockaddr_in6  *sin6;
  946. #endif

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

  948. #if (NGX_HAVE_INET6)
  949.     case AF_INET6:
  950.         sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;

  951.         v->len = sizeof(struct in6_addr);
  952.         v->valid = 1;
  953.         v->no_cacheable = 0;
  954.         v->not_found = 0;
  955.         v->data = sin6->sin6_addr.s6_addr;

  956.         break;
  957. #endif

  958. #if (NGX_HAVE_UNIX_DOMAIN)
  959.     case AF_UNIX:

  960.         v->len = r->connection->addr_text.len;
  961.         v->valid = 1;
  962.         v->no_cacheable = 0;
  963.         v->not_found = 0;
  964.         v->data = r->connection->addr_text.data;

  965.         break;
  966. #endif

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

  969.         v->len = sizeof(in_addr_t);
  970.         v->valid = 1;
  971.         v->no_cacheable = 0;
  972.         v->not_found = 0;
  973.         v->data = (u_char *) &sin->sin_addr;

  974.         break;
  975.     }

  976.     return NGX_OK;
  977. }


  978. static ngx_int_t
  979. ngx_http_variable_remote_addr(ngx_http_request_t *r,
  980.     ngx_http_variable_value_t *v, uintptr_t data)
  981. {
  982.     v->len = r->connection->addr_text.len;
  983.     v->valid = 1;
  984.     v->no_cacheable = 0;
  985.     v->not_found = 0;
  986.     v->data = r->connection->addr_text.data;

  987.     return NGX_OK;
  988. }


  989. static ngx_int_t
  990. ngx_http_variable_remote_port(ngx_http_request_t *r,
  991.     ngx_http_variable_value_t *v, uintptr_t data)
  992. {
  993.     ngx_uint_t  port;

  994.     v->len = 0;
  995.     v->valid = 1;
  996.     v->no_cacheable = 0;
  997.     v->not_found = 0;

  998.     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
  999.     if (v->data == NULL) {
  1000.         return NGX_ERROR;
  1001.     }

  1002.     port = ngx_inet_get_port(r->connection->sockaddr);

  1003.     if (port > 0 && port < 65536) {
  1004.         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
  1005.     }

  1006.     return NGX_OK;
  1007. }


  1008. static ngx_int_t
  1009. ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
  1010.     ngx_http_variable_value_t *v, uintptr_t data)
  1011. {
  1012.     ngx_str_t             *addr;
  1013.     ngx_proxy_protocol_t  *pp;

  1014.     pp = r->connection->proxy_protocol;
  1015.     if (pp == NULL) {
  1016.         v->not_found = 1;
  1017.         return NGX_OK;
  1018.     }

  1019.     addr = (ngx_str_t *) ((char *) pp + data);

  1020.     v->len = addr->len;
  1021.     v->valid = 1;
  1022.     v->no_cacheable = 0;
  1023.     v->not_found = 0;
  1024.     v->data = addr->data;

  1025.     return NGX_OK;
  1026. }


  1027. static ngx_int_t
  1028. ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
  1029.     ngx_http_variable_value_t *v, uintptr_t data)
  1030. {
  1031.     ngx_uint_t             port;
  1032.     ngx_proxy_protocol_t  *pp;

  1033.     pp = r->connection->proxy_protocol;
  1034.     if (pp == NULL) {
  1035.         v->not_found = 1;
  1036.         return NGX_OK;
  1037.     }

  1038.     v->len = 0;
  1039.     v->valid = 1;
  1040.     v->no_cacheable = 0;
  1041.     v->not_found = 0;

  1042.     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
  1043.     if (v->data == NULL) {
  1044.         return NGX_ERROR;
  1045.     }

  1046.     port = *(in_port_t *) ((char *) pp + data);

  1047.     if (port > 0 && port < 65536) {
  1048.         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
  1049.     }

  1050.     return NGX_OK;
  1051. }


  1052. static ngx_int_t
  1053. ngx_http_variable_proxy_protocol_tlv(ngx_http_request_t *r,
  1054.     ngx_http_variable_value_t *v, uintptr_t data)
  1055. {
  1056.     ngx_str_t *name = (ngx_str_t *) data;

  1057.     ngx_int_t  rc;
  1058.     ngx_str_t  tlv, value;

  1059.     tlv.len = name->len - (sizeof("proxy_protocol_tlv_") - 1);
  1060.     tlv.data = name->data + sizeof("proxy_protocol_tlv_") - 1;

  1061.     rc = ngx_proxy_protocol_get_tlv(r->connection, &tlv, &value);

  1062.     if (rc == NGX_ERROR) {
  1063.         return NGX_ERROR;
  1064.     }

  1065.     if (rc == NGX_DECLINED) {
  1066.         v->not_found = 1;
  1067.         return NGX_OK;
  1068.     }

  1069.     v->len = value.len;
  1070.     v->valid = 1;
  1071.     v->no_cacheable = 0;
  1072.     v->not_found = 0;
  1073.     v->data = value.data;

  1074.     return NGX_OK;
  1075. }


  1076. static ngx_int_t
  1077. ngx_http_variable_server_addr(ngx_http_request_t *r,
  1078.     ngx_http_variable_value_t *v, uintptr_t data)
  1079. {
  1080.     ngx_str_t  s;
  1081.     u_char     addr[NGX_SOCKADDR_STRLEN];

  1082.     s.len = NGX_SOCKADDR_STRLEN;
  1083.     s.data = addr;

  1084.     if (ngx_connection_local_sockaddr(r->connection, &s, 0) != NGX_OK) {
  1085.         return NGX_ERROR;
  1086.     }

  1087.     s.data = ngx_pnalloc(r->pool, s.len);
  1088.     if (s.data == NULL) {
  1089.         return NGX_ERROR;
  1090.     }

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

  1092.     v->len = s.len;
  1093.     v->valid = 1;
  1094.     v->no_cacheable = 0;
  1095.     v->not_found = 0;
  1096.     v->data = s.data;

  1097.     return NGX_OK;
  1098. }


  1099. static ngx_int_t
  1100. ngx_http_variable_server_port(ngx_http_request_t *r,
  1101.     ngx_http_variable_value_t *v, uintptr_t data)
  1102. {
  1103.     ngx_uint_t  port;

  1104.     v->len = 0;
  1105.     v->valid = 1;
  1106.     v->no_cacheable = 0;
  1107.     v->not_found = 0;

  1108.     if (ngx_connection_local_sockaddr(r->connection, NULL, 0) != NGX_OK) {
  1109.         return NGX_ERROR;
  1110.     }

  1111.     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
  1112.     if (v->data == NULL) {
  1113.         return NGX_ERROR;
  1114.     }

  1115.     port = ngx_inet_get_port(r->connection->local_sockaddr);

  1116.     if (port > 0 && port < 65536) {
  1117.         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
  1118.     }

  1119.     return NGX_OK;
  1120. }


  1121. static ngx_int_t
  1122. ngx_http_variable_scheme(ngx_http_request_t *r,
  1123.     ngx_http_variable_value_t *v, uintptr_t data)
  1124. {
  1125. #if (NGX_HTTP_SSL)

  1126.     if (r->connection->ssl) {
  1127.         v->len = sizeof("https") - 1;
  1128.         v->valid = 1;
  1129.         v->no_cacheable = 0;
  1130.         v->not_found = 0;
  1131.         v->data = (u_char *) "https";

  1132.         return NGX_OK;
  1133.     }

  1134. #endif

  1135.     v->len = sizeof("http") - 1;
  1136.     v->valid = 1;
  1137.     v->no_cacheable = 0;
  1138.     v->not_found = 0;
  1139.     v->data = (u_char *) "http";

  1140.     return NGX_OK;
  1141. }


  1142. static ngx_int_t
  1143. ngx_http_variable_https(ngx_http_request_t *r,
  1144.     ngx_http_variable_value_t *v, uintptr_t data)
  1145. {
  1146. #if (NGX_HTTP_SSL)

  1147.     if (r->connection->ssl) {
  1148.         v->len = sizeof("on") - 1;
  1149.         v->valid = 1;
  1150.         v->no_cacheable = 0;
  1151.         v->not_found = 0;
  1152.         v->data = (u_char *) "on";

  1153.         return NGX_OK;
  1154.     }

  1155. #endif

  1156.     *v = ngx_http_variable_null_value;

  1157.     return NGX_OK;
  1158. }


  1159. static void
  1160. ngx_http_variable_set_args(ngx_http_request_t *r,
  1161.     ngx_http_variable_value_t *v, uintptr_t data)
  1162. {
  1163.     r->args.len = v->len;
  1164.     r->args.data = v->data;
  1165.     r->valid_unparsed_uri = 0;
  1166. }


  1167. static ngx_int_t
  1168. ngx_http_variable_is_args(ngx_http_request_t *r,
  1169.     ngx_http_variable_value_t *v, uintptr_t data)
  1170. {
  1171.     if (r->args.len == 0) {
  1172.         *v = ngx_http_variable_null_value;
  1173.         return NGX_OK;
  1174.     }

  1175.     v->len = 1;
  1176.     v->valid = 1;
  1177.     v->no_cacheable = 0;
  1178.     v->not_found = 0;
  1179.     v->data = (u_char *) "?";

  1180.     return NGX_OK;
  1181. }


  1182. static ngx_int_t
  1183. ngx_http_variable_document_root(ngx_http_request_t *r,
  1184.     ngx_http_variable_value_t *v, uintptr_t data)
  1185. {
  1186.     ngx_str_t                  path;
  1187.     ngx_http_core_loc_conf_t  *clcf;

  1188.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1189.     if (clcf->root_lengths == NULL) {
  1190.         v->len = clcf->root.len;
  1191.         v->valid = 1;
  1192.         v->no_cacheable = 0;
  1193.         v->not_found = 0;
  1194.         v->data = clcf->root.data;

  1195.     } else {
  1196.         if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 0,
  1197.                                 clcf->root_values->elts)
  1198.             == NULL)
  1199.         {
  1200.             return NGX_ERROR;
  1201.         }

  1202.         if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, &path)
  1203.             != NGX_OK)
  1204.         {
  1205.             return NGX_ERROR;
  1206.         }

  1207.         v->len = path.len;
  1208.         v->valid = 1;
  1209.         v->no_cacheable = 0;
  1210.         v->not_found = 0;
  1211.         v->data = path.data;
  1212.     }

  1213.     return NGX_OK;
  1214. }


  1215. static ngx_int_t
  1216. ngx_http_variable_realpath_root(ngx_http_request_t *r,
  1217.     ngx_http_variable_value_t *v, uintptr_t data)
  1218. {
  1219.     u_char                    *real;
  1220.     size_t                     len;
  1221.     ngx_str_t                  path;
  1222.     ngx_http_core_loc_conf_t  *clcf;
  1223. #if (NGX_HAVE_MAX_PATH)
  1224.     u_char                     buffer[NGX_MAX_PATH];
  1225. #endif

  1226.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1227.     if (clcf->root_lengths == NULL) {
  1228.         path = clcf->root;

  1229.     } else {
  1230.         if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 1,
  1231.                                 clcf->root_values->elts)
  1232.             == NULL)
  1233.         {
  1234.             return NGX_ERROR;
  1235.         }

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

  1237.         if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, &path)
  1238.             != NGX_OK)
  1239.         {
  1240.             return NGX_ERROR;
  1241.         }
  1242.     }

  1243. #if (NGX_HAVE_MAX_PATH)
  1244.     real = buffer;
  1245. #else
  1246.     real = NULL;
  1247. #endif

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

  1249.     if (real == NULL) {
  1250.         ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
  1251.                       ngx_realpath_n " \"%s\" failed", path.data);
  1252.         return NGX_ERROR;
  1253.     }

  1254.     len = ngx_strlen(real);

  1255.     v->data = ngx_pnalloc(r->pool, len);
  1256.     if (v->data == NULL) {
  1257. #if !(NGX_HAVE_MAX_PATH)
  1258.         ngx_free(real);
  1259. #endif
  1260.         return NGX_ERROR;
  1261.     }

  1262.     v->len = len;
  1263.     v->valid = 1;
  1264.     v->no_cacheable = 0;
  1265.     v->not_found = 0;

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

  1267. #if !(NGX_HAVE_MAX_PATH)
  1268.     ngx_free(real);
  1269. #endif

  1270.     return NGX_OK;
  1271. }


  1272. static ngx_int_t
  1273. ngx_http_variable_request_filename(ngx_http_request_t *r,
  1274.     ngx_http_variable_value_t *v, uintptr_t data)
  1275. {
  1276.     size_t     root;
  1277.     ngx_str_t  path;

  1278.     if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
  1279.         return NGX_ERROR;
  1280.     }

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

  1282.     v->len = path.len - 1;
  1283.     v->valid = 1;
  1284.     v->no_cacheable = 0;
  1285.     v->not_found = 0;
  1286.     v->data = path.data;

  1287.     return NGX_OK;
  1288. }


  1289. static ngx_int_t
  1290. ngx_http_variable_server_name(ngx_http_request_t *r,
  1291.     ngx_http_variable_value_t *v, uintptr_t data)
  1292. {
  1293.     ngx_http_core_srv_conf_t  *cscf;

  1294.     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);

  1295.     v->len = cscf->server_name.len;
  1296.     v->valid = 1;
  1297.     v->no_cacheable = 0;
  1298.     v->not_found = 0;
  1299.     v->data = cscf->server_name.data;

  1300.     return NGX_OK;
  1301. }


  1302. static ngx_int_t
  1303. ngx_http_variable_request_method(ngx_http_request_t *r,
  1304.     ngx_http_variable_value_t *v, uintptr_t data)
  1305. {
  1306.     if (r->main->method_name.data) {
  1307.         v->len = r->main->method_name.len;
  1308.         v->valid = 1;
  1309.         v->no_cacheable = 0;
  1310.         v->not_found = 0;
  1311.         v->data = r->main->method_name.data;

  1312.     } else {
  1313.         v->not_found = 1;
  1314.     }

  1315.     return NGX_OK;
  1316. }


  1317. static ngx_int_t
  1318. ngx_http_variable_remote_user(ngx_http_request_t *r,
  1319.     ngx_http_variable_value_t *v, uintptr_t data)
  1320. {
  1321.     ngx_int_t  rc;

  1322.     rc = ngx_http_auth_basic_user(r);

  1323.     if (rc == NGX_DECLINED) {
  1324.         v->not_found = 1;
  1325.         return NGX_OK;
  1326.     }

  1327.     if (rc == NGX_ERROR) {
  1328.         return NGX_ERROR;
  1329.     }

  1330.     v->len = r->headers_in.user.len;
  1331.     v->valid = 1;
  1332.     v->no_cacheable = 0;
  1333.     v->not_found = 0;
  1334.     v->data = r->headers_in.user.data;

  1335.     return NGX_OK;
  1336. }


  1337. static ngx_int_t
  1338. ngx_http_variable_bytes_sent(ngx_http_request_t *r,
  1339.     ngx_http_variable_value_t *v, uintptr_t data)
  1340. {
  1341.     u_char  *p;

  1342.     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
  1343.     if (p == NULL) {
  1344.         return NGX_ERROR;
  1345.     }

  1346.     v->len = ngx_sprintf(p, "%O", r->connection->sent) - p;
  1347.     v->valid = 1;
  1348.     v->no_cacheable = 0;
  1349.     v->not_found = 0;
  1350.     v->data = p;

  1351.     return NGX_OK;
  1352. }


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

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

  1360.     if (sent < 0) {
  1361.         sent = 0;
  1362.     }

  1363.     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
  1364.     if (p == NULL) {
  1365.         return NGX_ERROR;
  1366.     }

  1367.     v->len = ngx_sprintf(p, "%O", sent) - p;
  1368.     v->valid = 1;
  1369.     v->no_cacheable = 0;
  1370.     v->not_found = 0;
  1371.     v->data = p;

  1372.     return NGX_OK;
  1373. }


  1374. static ngx_int_t
  1375. ngx_http_variable_pipe(ngx_http_request_t *r,
  1376.     ngx_http_variable_value_t *v, uintptr_t data)
  1377. {
  1378.     v->data = (u_char *) (r->pipeline ? "p" : ".");
  1379.     v->len = 1;
  1380.     v->valid = 1;
  1381.     v->no_cacheable = 0;
  1382.     v->not_found = 0;

  1383.     return NGX_OK;
  1384. }


  1385. static ngx_int_t
  1386. ngx_http_variable_status(ngx_http_request_t *r,
  1387.     ngx_http_variable_value_t *v, uintptr_t data)
  1388. {
  1389.     ngx_uint_t  status;

  1390.     v->data = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
  1391.     if (v->data == NULL) {
  1392.         return NGX_ERROR;
  1393.     }

  1394.     if (r->err_status) {
  1395.         status = r->err_status;

  1396.     } else if (r->headers_out.status) {
  1397.         status = r->headers_out.status;

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

  1400.     } else {
  1401.         status = 0;
  1402.     }

  1403.     v->len = ngx_sprintf(v->data, "%03ui", status) - v->data;
  1404.     v->valid = 1;
  1405.     v->no_cacheable = 0;
  1406.     v->not_found = 0;

  1407.     return NGX_OK;
  1408. }


  1409. static ngx_int_t
  1410. ngx_http_variable_sent_content_type(ngx_http_request_t *r,
  1411.     ngx_http_variable_value_t *v, uintptr_t data)
  1412. {
  1413.     if (r->headers_out.content_type.len) {
  1414.         v->len = r->headers_out.content_type.len;
  1415.         v->valid = 1;
  1416.         v->no_cacheable = 0;
  1417.         v->not_found = 0;
  1418.         v->data = r->headers_out.content_type.data;

  1419.     } else {
  1420.         v->not_found = 1;
  1421.     }

  1422.     return NGX_OK;
  1423. }


  1424. static ngx_int_t
  1425. ngx_http_variable_sent_content_length(ngx_http_request_t *r,
  1426.     ngx_http_variable_value_t *v, uintptr_t data)
  1427. {
  1428.     u_char  *p;

  1429.     if (r->headers_out.content_length) {
  1430.         v->len = r->headers_out.content_length->value.len;
  1431.         v->valid = 1;
  1432.         v->no_cacheable = 0;
  1433.         v->not_found = 0;
  1434.         v->data = r->headers_out.content_length->value.data;

  1435.         return NGX_OK;
  1436.     }

  1437.     if (r->headers_out.content_length_n >= 0) {
  1438.         p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
  1439.         if (p == NULL) {
  1440.             return NGX_ERROR;
  1441.         }

  1442.         v->len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) - p;
  1443.         v->valid = 1;
  1444.         v->no_cacheable = 0;
  1445.         v->not_found = 0;
  1446.         v->data = p;

  1447.         return NGX_OK;
  1448.     }

  1449.     v->not_found = 1;

  1450.     return NGX_OK;
  1451. }


  1452. static ngx_int_t
  1453. ngx_http_variable_sent_location(ngx_http_request_t *r,
  1454.     ngx_http_variable_value_t *v, uintptr_t data)
  1455. {
  1456.     ngx_str_t  name;

  1457.     if (r->headers_out.location) {
  1458.         v->len = r->headers_out.location->value.len;
  1459.         v->valid = 1;
  1460.         v->no_cacheable = 0;
  1461.         v->not_found = 0;
  1462.         v->data = r->headers_out.location->value.data;

  1463.         return NGX_OK;
  1464.     }

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

  1466.     return ngx_http_variable_unknown_header(r, v, &name,
  1467.                                             &r->headers_out.headers.part,
  1468.                                             sizeof("sent_http_") - 1);
  1469. }


  1470. static ngx_int_t
  1471. ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
  1472.     ngx_http_variable_value_t *v, uintptr_t data)
  1473. {
  1474.     u_char  *p;

  1475.     if (r->headers_out.last_modified) {
  1476.         v->len = r->headers_out.last_modified->value.len;
  1477.         v->valid = 1;
  1478.         v->no_cacheable = 0;
  1479.         v->not_found = 0;
  1480.         v->data = r->headers_out.last_modified->value.data;

  1481.         return NGX_OK;
  1482.     }

  1483.     if (r->headers_out.last_modified_time >= 0) {
  1484.         p = ngx_pnalloc(r->pool, sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1);
  1485.         if (p == NULL) {
  1486.             return NGX_ERROR;
  1487.         }

  1488.         v->len = ngx_http_time(p, r->headers_out.last_modified_time) - p;
  1489.         v->valid = 1;
  1490.         v->no_cacheable = 0;
  1491.         v->not_found = 0;
  1492.         v->data = p;

  1493.         return NGX_OK;
  1494.     }

  1495.     v->not_found = 1;

  1496.     return NGX_OK;
  1497. }


  1498. static ngx_int_t
  1499. ngx_http_variable_sent_connection(ngx_http_request_t *r,
  1500.     ngx_http_variable_value_t *v, uintptr_t data)
  1501. {
  1502.     size_t   len;
  1503.     char    *p;

  1504.     if (r->headers_out.status == NGX_HTTP_SWITCHING_PROTOCOLS) {
  1505.         len = sizeof("upgrade") - 1;
  1506.         p = "upgrade";

  1507.     } else if (r->keepalive) {
  1508.         len = sizeof("keep-alive") - 1;
  1509.         p = "keep-alive";

  1510.     } else {
  1511.         len = sizeof("close") - 1;
  1512.         p = "close";
  1513.     }

  1514.     v->len = len;
  1515.     v->valid = 1;
  1516.     v->no_cacheable = 0;
  1517.     v->not_found = 0;
  1518.     v->data = (u_char *) p;

  1519.     return NGX_OK;
  1520. }


  1521. static ngx_int_t
  1522. ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
  1523.     ngx_http_variable_value_t *v, uintptr_t data)
  1524. {
  1525.     u_char                    *p;
  1526.     ngx_http_core_loc_conf_t  *clcf;

  1527.     if (r->keepalive) {
  1528.         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  1529.         if (clcf->keepalive_header) {

  1530.             p = ngx_pnalloc(r->pool, sizeof("timeout=") - 1 + NGX_TIME_T_LEN);
  1531.             if (p == NULL) {
  1532.                 return NGX_ERROR;
  1533.             }

  1534.             v->len = ngx_sprintf(p, "timeout=%T", clcf->keepalive_header) - p;
  1535.             v->valid = 1;
  1536.             v->no_cacheable = 0;
  1537.             v->not_found = 0;
  1538.             v->data = p;

  1539.             return NGX_OK;
  1540.         }
  1541.     }

  1542.     v->not_found = 1;

  1543.     return NGX_OK;
  1544. }


  1545. static ngx_int_t
  1546. ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
  1547.     ngx_http_variable_value_t *v, uintptr_t data)
  1548. {
  1549.     if (r->chunked) {
  1550.         v->len = sizeof("chunked") - 1;
  1551.         v->valid = 1;
  1552.         v->no_cacheable = 0;
  1553.         v->not_found = 0;
  1554.         v->data = (u_char *) "chunked";

  1555.     } else {
  1556.         v->not_found = 1;
  1557.     }

  1558.     return NGX_OK;
  1559. }


  1560. static void
  1561. ngx_http_variable_set_limit_rate(ngx_http_request_t *r,
  1562.     ngx_http_variable_value_t *v, uintptr_t data)
  1563. {
  1564.     ssize_t    s;
  1565.     ngx_str_t  val;

  1566.     val.len = v->len;
  1567.     val.data = v->data;

  1568.     s = ngx_parse_size(&val);

  1569.     if (s == NGX_ERROR) {
  1570.         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  1571.                       "invalid $limit_rate \"%V\"", &val);
  1572.         return;
  1573.     }

  1574.     r->limit_rate = s;
  1575.     r->limit_rate_set = 1;
  1576. }


  1577. static ngx_int_t
  1578. ngx_http_variable_request_completion(ngx_http_request_t *r,
  1579.     ngx_http_variable_value_t *v, uintptr_t data)
  1580. {
  1581.     if (r->request_complete) {
  1582.         v->len = 2;
  1583.         v->valid = 1;
  1584.         v->no_cacheable = 0;
  1585.         v->not_found = 0;
  1586.         v->data = (u_char *) "OK";

  1587.         return NGX_OK;
  1588.     }

  1589.     *v = ngx_http_variable_null_value;

  1590.     return NGX_OK;
  1591. }


  1592. static ngx_int_t
  1593. ngx_http_variable_request_body(ngx_http_request_t *r,
  1594.     ngx_http_variable_value_t *v, uintptr_t data)
  1595. {
  1596.     u_char       *p;
  1597.     size_t        len;
  1598.     ngx_buf_t    *buf;
  1599.     ngx_chain_t  *cl;

  1600.     if (r->request_body == NULL
  1601.         || r->request_body->bufs == NULL
  1602.         || r->request_body->temp_file)
  1603.     {
  1604.         v->not_found = 1;

  1605.         return NGX_OK;
  1606.     }

  1607.     cl = r->request_body->bufs;
  1608.     buf = cl->buf;

  1609.     if (cl->next == NULL) {
  1610.         v->len = buf->last - buf->pos;
  1611.         v->valid = 1;
  1612.         v->no_cacheable = 0;
  1613.         v->not_found = 0;
  1614.         v->data = buf->pos;

  1615.         return NGX_OK;
  1616.     }

  1617.     len = buf->last - buf->pos;
  1618.     cl = cl->next;

  1619.     for ( /* void */ ; cl; cl = cl->next) {
  1620.         buf = cl->buf;
  1621.         len += buf->last - buf->pos;
  1622.     }

  1623.     p = ngx_pnalloc(r->pool, len);
  1624.     if (p == NULL) {
  1625.         return NGX_ERROR;
  1626.     }

  1627.     v->data = p;
  1628.     cl = r->request_body->bufs;

  1629.     for ( /* void */ ; cl; cl = cl->next) {
  1630.         buf = cl->buf;
  1631.         p = ngx_cpymem(p, buf->pos, buf->last - buf->pos);
  1632.     }

  1633.     v->len = len;
  1634.     v->valid = 1;
  1635.     v->no_cacheable = 0;
  1636.     v->not_found = 0;

  1637.     return NGX_OK;
  1638. }


  1639. static ngx_int_t
  1640. ngx_http_variable_request_body_file(ngx_http_request_t *r,
  1641.     ngx_http_variable_value_t *v, uintptr_t data)
  1642. {
  1643.     if (r->request_body == NULL || r->request_body->temp_file == NULL) {
  1644.         v->not_found = 1;

  1645.         return NGX_OK;
  1646.     }

  1647.     v->len = r->request_body->temp_file->file.name.len;
  1648.     v->valid = 1;
  1649.     v->no_cacheable = 0;
  1650.     v->not_found = 0;
  1651.     v->data = r->request_body->temp_file->file.name.data;

  1652.     return NGX_OK;
  1653. }


  1654. static ngx_int_t
  1655. ngx_http_variable_request_length(ngx_http_request_t *r,
  1656.     ngx_http_variable_value_t *v, uintptr_t data)
  1657. {
  1658.     u_char  *p;

  1659.     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
  1660.     if (p == NULL) {
  1661.         return NGX_ERROR;
  1662.     }

  1663.     v->len = ngx_sprintf(p, "%O", r->request_length) - p;
  1664.     v->valid = 1;
  1665.     v->no_cacheable = 0;
  1666.     v->not_found = 0;
  1667.     v->data = p;

  1668.     return NGX_OK;
  1669. }


  1670. static ngx_int_t
  1671. ngx_http_variable_request_time(ngx_http_request_t *r,
  1672.     ngx_http_variable_value_t *v, uintptr_t data)
  1673. {
  1674.     u_char          *p;
  1675.     ngx_time_t      *tp;
  1676.     ngx_msec_int_t   ms;

  1677.     p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4);
  1678.     if (p == NULL) {
  1679.         return NGX_ERROR;
  1680.     }

  1681.     tp = ngx_timeofday();

  1682.     ms = (ngx_msec_int_t)
  1683.              ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec));
  1684.     ms = ngx_max(ms, 0);

  1685.     v->len = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000) - p;
  1686.     v->valid = 1;
  1687.     v->no_cacheable = 0;
  1688.     v->not_found = 0;
  1689.     v->data = p;

  1690.     return NGX_OK;
  1691. }


  1692. static ngx_int_t
  1693. ngx_http_variable_request_id(ngx_http_request_t *r,
  1694.     ngx_http_variable_value_t *v, uintptr_t data)
  1695. {
  1696.     u_char  *id;

  1697. #if (NGX_OPENSSL)
  1698.     u_char   random_bytes[16];
  1699. #endif

  1700.     id = ngx_pnalloc(r->pool, 32);
  1701.     if (id == NULL) {
  1702.         return NGX_ERROR;
  1703.     }

  1704.     v->valid = 1;
  1705.     v->no_cacheable = 0;
  1706.     v->not_found = 0;

  1707.     v->len = 32;
  1708.     v->data = id;

  1709. #if (NGX_OPENSSL)

  1710.     if (RAND_bytes(random_bytes, 16) == 1) {
  1711.         ngx_hex_dump(id, random_bytes, 16);
  1712.         return NGX_OK;
  1713.     }

  1714.     ngx_ssl_error(NGX_LOG_ERR, r->connection->log, 0, "RAND_bytes() failed");

  1715. #endif

  1716.     ngx_sprintf(id, "%08xD%08xD%08xD%08xD",
  1717.                 (uint32_t) ngx_random(), (uint32_t) ngx_random(),
  1718.                 (uint32_t) ngx_random(), (uint32_t) ngx_random());

  1719.     return NGX_OK;
  1720. }


  1721. static ngx_int_t
  1722. ngx_http_variable_connection(ngx_http_request_t *r,
  1723.     ngx_http_variable_value_t *v, uintptr_t data)
  1724. {
  1725.     u_char  *p;

  1726.     p = ngx_pnalloc(r->pool, NGX_ATOMIC_T_LEN);
  1727.     if (p == NULL) {
  1728.         return NGX_ERROR;
  1729.     }

  1730.     v->len = ngx_sprintf(p, "%uA", r->connection->number) - p;
  1731.     v->valid = 1;
  1732.     v->no_cacheable = 0;
  1733.     v->not_found = 0;
  1734.     v->data = p;

  1735.     return NGX_OK;
  1736. }


  1737. static ngx_int_t
  1738. ngx_http_variable_connection_requests(ngx_http_request_t *r,
  1739.     ngx_http_variable_value_t *v, uintptr_t data)
  1740. {
  1741.     u_char  *p;

  1742.     p = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
  1743.     if (p == NULL) {
  1744.         return NGX_ERROR;
  1745.     }

  1746.     v->len = ngx_sprintf(p, "%ui", r->connection->requests) - p;
  1747.     v->valid = 1;
  1748.     v->no_cacheable = 0;
  1749.     v->not_found = 0;
  1750.     v->data = p;

  1751.     return NGX_OK;
  1752. }


  1753. static ngx_int_t
  1754. ngx_http_variable_connection_time(ngx_http_request_t *r,
  1755.     ngx_http_variable_value_t *v, uintptr_t data)
  1756. {
  1757.     u_char          *p;
  1758.     ngx_msec_int_t   ms;

  1759.     p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4);
  1760.     if (p == NULL) {
  1761.         return NGX_ERROR;
  1762.     }

  1763.     ms = ngx_current_msec - r->connection->start_time;
  1764.     ms = ngx_max(ms, 0);

  1765.     v->len = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000) - p;
  1766.     v->valid = 1;
  1767.     v->no_cacheable = 0;
  1768.     v->not_found = 0;
  1769.     v->data = p;

  1770.     return NGX_OK;
  1771. }


  1772. static ngx_int_t
  1773. ngx_http_variable_nginx_version(ngx_http_request_t *r,
  1774.     ngx_http_variable_value_t *v, uintptr_t data)
  1775. {
  1776.     v->len = sizeof(NGINX_VERSION) - 1;
  1777.     v->valid = 1;
  1778.     v->no_cacheable = 0;
  1779.     v->not_found = 0;
  1780.     v->data = (u_char *) NGINX_VERSION;

  1781.     return NGX_OK;
  1782. }


  1783. static ngx_int_t
  1784. ngx_http_variable_hostname(ngx_http_request_t *r,
  1785.     ngx_http_variable_value_t *v, uintptr_t data)
  1786. {
  1787.     v->len = ngx_cycle->hostname.len;
  1788.     v->valid = 1;
  1789.     v->no_cacheable = 0;
  1790.     v->not_found = 0;
  1791.     v->data = ngx_cycle->hostname.data;

  1792.     return NGX_OK;
  1793. }


  1794. static ngx_int_t
  1795. ngx_http_variable_pid(ngx_http_request_t *r,
  1796.     ngx_http_variable_value_t *v, uintptr_t data)
  1797. {
  1798.     u_char  *p;

  1799.     p = ngx_pnalloc(r->pool, NGX_INT64_LEN);
  1800.     if (p == NULL) {
  1801.         return NGX_ERROR;
  1802.     }

  1803.     v->len = ngx_sprintf(p, "%P", ngx_pid) - p;
  1804.     v->valid = 1;
  1805.     v->no_cacheable = 0;
  1806.     v->not_found = 0;
  1807.     v->data = p;

  1808.     return NGX_OK;
  1809. }


  1810. static ngx_int_t
  1811. ngx_http_variable_msec(ngx_http_request_t *r,
  1812.     ngx_http_variable_value_t *v, uintptr_t data)
  1813. {
  1814.     u_char      *p;
  1815.     ngx_time_t  *tp;

  1816.     p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4);
  1817.     if (p == NULL) {
  1818.         return NGX_ERROR;
  1819.     }

  1820.     tp = ngx_timeofday();

  1821.     v->len = ngx_sprintf(p, "%T.%03M", tp->sec, tp->msec) - p;
  1822.     v->valid = 1;
  1823.     v->no_cacheable = 0;
  1824.     v->not_found = 0;
  1825.     v->data = p;

  1826.     return NGX_OK;
  1827. }


  1828. static ngx_int_t
  1829. ngx_http_variable_time_iso8601(ngx_http_request_t *r,
  1830.     ngx_http_variable_value_t *v, uintptr_t data)
  1831. {
  1832.     u_char  *p;

  1833.     p = ngx_pnalloc(r->pool, ngx_cached_http_log_iso8601.len);
  1834.     if (p == NULL) {
  1835.         return NGX_ERROR;
  1836.     }

  1837.     ngx_memcpy(p, ngx_cached_http_log_iso8601.data,
  1838.                ngx_cached_http_log_iso8601.len);

  1839.     v->len = ngx_cached_http_log_iso8601.len;
  1840.     v->valid = 1;
  1841.     v->no_cacheable = 0;
  1842.     v->not_found = 0;
  1843.     v->data = p;

  1844.     return NGX_OK;
  1845. }


  1846. static ngx_int_t
  1847. ngx_http_variable_time_local(ngx_http_request_t *r,
  1848.     ngx_http_variable_value_t *v, uintptr_t data)
  1849. {
  1850.     u_char  *p;

  1851.     p = ngx_pnalloc(r->pool, ngx_cached_http_log_time.len);
  1852.     if (p == NULL) {
  1853.         return NGX_ERROR;
  1854.     }

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

  1856.     v->len = ngx_cached_http_log_time.len;
  1857.     v->valid = 1;
  1858.     v->no_cacheable = 0;
  1859.     v->not_found = 0;
  1860.     v->data = p;

  1861.     return NGX_OK;
  1862. }


  1863. void *
  1864. ngx_http_map_find(ngx_http_request_t *r, ngx_http_map_t *map, ngx_str_t *match)
  1865. {
  1866.     void        *value;
  1867.     u_char      *low;
  1868.     size_t       len;
  1869.     ngx_uint_t   key;

  1870.     len = match->len;

  1871.     if (len) {
  1872.         low = ngx_pnalloc(r->pool, len);
  1873.         if (low == NULL) {
  1874.             return NULL;
  1875.         }

  1876.     } else {
  1877.         low = NULL;
  1878.     }

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

  1880.     value = ngx_hash_find_combined(&map->hash, key, low, len);
  1881.     if (value) {
  1882.         return value;
  1883.     }

  1884. #if (NGX_PCRE)

  1885.     if (len && map->nregex) {
  1886.         ngx_int_t              n;
  1887.         ngx_uint_t             i;
  1888.         ngx_http_map_regex_t  *reg;

  1889.         reg = map->regex;

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

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

  1892.             if (n == NGX_OK) {
  1893.                 return reg[i].value;
  1894.             }

  1895.             if (n == NGX_DECLINED) {
  1896.                 continue;
  1897.             }

  1898.             /* NGX_ERROR */

  1899.             return NULL;
  1900.         }
  1901.     }

  1902. #endif

  1903.     return NULL;
  1904. }


  1905. #if (NGX_PCRE)

  1906. static ngx_int_t
  1907. ngx_http_variable_not_found(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  1908.     uintptr_t data)
  1909. {
  1910.     v->not_found = 1;
  1911.     return NGX_OK;
  1912. }


  1913. ngx_http_regex_t *
  1914. ngx_http_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc)
  1915. {
  1916.     u_char                     *p;
  1917.     size_t                      size;
  1918.     ngx_str_t                   name;
  1919.     ngx_uint_t                  i, n;
  1920.     ngx_http_variable_t        *v;
  1921.     ngx_http_regex_t           *re;
  1922.     ngx_http_regex_variable_t  *rv;
  1923.     ngx_http_core_main_conf_t  *cmcf;

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

  1925.     if (ngx_regex_compile(rc) != NGX_OK) {
  1926.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err);
  1927.         return NULL;
  1928.     }

  1929.     re = ngx_pcalloc(cf->pool, sizeof(ngx_http_regex_t));
  1930.     if (re == NULL) {
  1931.         return NULL;
  1932.     }

  1933.     re->regex = rc->regex;
  1934.     re->ncaptures = rc->captures;
  1935.     re->name = rc->pattern;

  1936.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
  1937.     cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures);

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

  1939.     if (n == 0) {
  1940.         return re;
  1941.     }

  1942.     rv = ngx_palloc(rc->pool, n * sizeof(ngx_http_regex_variable_t));
  1943.     if (rv == NULL) {
  1944.         return NULL;
  1945.     }

  1946.     re->variables = rv;
  1947.     re->nvariables = n;

  1948.     size = rc->name_size;
  1949.     p = rc->names;

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

  1952.         name.data = &p[2];
  1953.         name.len = ngx_strlen(name.data);

  1954.         v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
  1955.         if (v == NULL) {
  1956.             return NULL;
  1957.         }

  1958.         rv[i].index = ngx_http_get_variable_index(cf, &name);
  1959.         if (rv[i].index == NGX_ERROR) {
  1960.             return NULL;
  1961.         }

  1962.         v->get_handler = ngx_http_variable_not_found;

  1963.         p += size;
  1964.     }

  1965.     return re;
  1966. }


  1967. ngx_int_t
  1968. ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, ngx_str_t *s)
  1969. {
  1970.     ngx_int_t                   rc, index;
  1971.     ngx_uint_t                  i, n, len;
  1972.     ngx_http_variable_value_t  *vv;
  1973.     ngx_http_core_main_conf_t  *cmcf;

  1974.     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

  1975.     if (re->ncaptures) {
  1976.         len = cmcf->ncaptures;

  1977.         if (r->captures == NULL || r->realloc_captures) {
  1978.             r->realloc_captures = 0;

  1979.             r->captures = ngx_palloc(r->pool, len * sizeof(int));
  1980.             if (r->captures == NULL) {
  1981.                 return NGX_ERROR;
  1982.             }
  1983.         }

  1984.     } else {
  1985.         len = 0;
  1986.     }

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

  1988.     if (rc == NGX_REGEX_NO_MATCHED) {
  1989.         return NGX_DECLINED;
  1990.     }

  1991.     if (rc < 0) {
  1992.         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  1993.                       ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
  1994.                       rc, s, &re->name);
  1995.         return NGX_ERROR;
  1996.     }

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

  1998.         n = re->variables[i].capture;
  1999.         index = re->variables[i].index;
  2000.         vv = &r->variables[index];

  2001.         vv->len = r->captures[n + 1] - r->captures[n];
  2002.         vv->valid = 1;
  2003.         vv->no_cacheable = 0;
  2004.         vv->not_found = 0;
  2005.         vv->data = &s->data[r->captures[n]];

  2006. #if (NGX_DEBUG)
  2007.         {
  2008.         ngx_http_variable_t  *v;

  2009.         v = cmcf->variables.elts;

  2010.         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  2011.                        "http regex set $%V to \"%v\"", &v[index].name, vv);
  2012.         }
  2013. #endif
  2014.     }

  2015.     r->ncaptures = rc * 2;
  2016.     r->captures_data = s->data;

  2017.     return NGX_OK;
  2018. }

  2019. #endif


  2020. ngx_int_t
  2021. ngx_http_variables_add_core_vars(ngx_conf_t *cf)
  2022. {
  2023.     ngx_http_variable_t        *cv, *v;
  2024.     ngx_http_core_main_conf_t  *cmcf;

  2025.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

  2026.     cmcf->variables_keys = ngx_pcalloc(cf->temp_pool,
  2027.                                        sizeof(ngx_hash_keys_arrays_t));
  2028.     if (cmcf->variables_keys == NULL) {
  2029.         return NGX_ERROR;
  2030.     }

  2031.     cmcf->variables_keys->pool = cf->pool;
  2032.     cmcf->variables_keys->temp_pool = cf->pool;

  2033.     if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL)
  2034.         != NGX_OK)
  2035.     {
  2036.         return NGX_ERROR;
  2037.     }

  2038.     if (ngx_array_init(&cmcf->prefix_variables, cf->pool, 8,
  2039.                        sizeof(ngx_http_variable_t))
  2040.         != NGX_OK)
  2041.     {
  2042.         return NGX_ERROR;
  2043.     }

  2044.     for (cv = ngx_http_core_variables; cv->name.len; cv++) {
  2045.         v = ngx_http_add_variable(cf, &cv->name, cv->flags);
  2046.         if (v == NULL) {
  2047.             return NGX_ERROR;
  2048.         }

  2049.         *v = *cv;
  2050.     }

  2051.     return NGX_OK;
  2052. }


  2053. ngx_int_t
  2054. ngx_http_variables_init_vars(ngx_conf_t *cf)
  2055. {
  2056.     size_t                      len;
  2057.     ngx_uint_t                  i, n;
  2058.     ngx_hash_key_t             *key;
  2059.     ngx_hash_init_t             hash;
  2060.     ngx_http_variable_t        *v, *av, *pv;
  2061.     ngx_http_core_main_conf_t  *cmcf;

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

  2063.     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

  2064.     v = cmcf->variables.elts;
  2065.     pv = cmcf->prefix_variables.elts;
  2066.     key = cmcf->variables_keys->keys.elts;

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

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

  2069.             av = key[n].value;

  2070.             if (v[i].name.len == key[n].key.len
  2071.                 && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len)
  2072.                    == 0)
  2073.             {
  2074.                 v[i].get_handler = av->get_handler;
  2075.                 v[i].data = av->data;

  2076.                 av->flags |= NGX_HTTP_VAR_INDEXED;
  2077.                 v[i].flags = av->flags;

  2078.                 av->index = i;

  2079.                 if (av->get_handler == NULL
  2080.                     || (av->flags & NGX_HTTP_VAR_WEAK))
  2081.                 {
  2082.                     break;
  2083.                 }

  2084.                 goto next;
  2085.             }
  2086.         }

  2087.         len = 0;
  2088.         av = NULL;

  2089.         for (n = 0; n < cmcf->prefix_variables.nelts; n++) {
  2090.             if (v[i].name.len >= pv[n].name.len && v[i].name.len > len
  2091.                 && ngx_strncmp(v[i].name.data, pv[n].name.data, pv[n].name.len)
  2092.                    == 0)
  2093.             {
  2094.                 av = &pv[n];
  2095.                 len = pv[n].name.len;
  2096.             }
  2097.         }

  2098.         if (av) {
  2099.             v[i].get_handler = av->get_handler;
  2100.             v[i].data = (uintptr_t) &v[i].name;
  2101.             v[i].flags = av->flags;

  2102.             goto next;
  2103.         }

  2104.         if (v[i].get_handler == NULL) {
  2105.             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
  2106.                           "unknown \"%V\" variable", &v[i].name);

  2107.             return NGX_ERROR;
  2108.         }

  2109.     next:
  2110.         continue;
  2111.     }


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

  2114.         if (av->flags & NGX_HTTP_VAR_NOHASH) {
  2115.             key[n].key.data = NULL;
  2116.         }
  2117.     }


  2118.     hash.hash = &cmcf->variables_hash;
  2119.     hash.key = ngx_hash_key;
  2120.     hash.max_size = cmcf->variables_hash_max_size;
  2121.     hash.bucket_size = cmcf->variables_hash_bucket_size;
  2122.     hash.name = "variables_hash";
  2123.     hash.pool = cf->pool;
  2124.     hash.temp_pool = NULL;

  2125.     if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts,
  2126.                       cmcf->variables_keys->keys.nelts)
  2127.         != NGX_OK)
  2128.     {
  2129.         return NGX_ERROR;
  2130.     }

  2131.     cmcf->variables_keys = NULL;

  2132.     return NGX_OK;
  2133. }