Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_http.h>
0011 #include <nginx.h>
0012 
0013 
0014 static ngx_http_variable_t *ngx_http_add_prefix_variable(ngx_conf_t *cf,
0015     ngx_str_t *name, ngx_uint_t flags);
0016 
0017 static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r,
0018     ngx_http_variable_value_t *v, uintptr_t data);
0019 #if 0
0020 static void ngx_http_variable_request_set(ngx_http_request_t *r,
0021     ngx_http_variable_value_t *v, uintptr_t data);
0022 #endif
0023 static ngx_int_t ngx_http_variable_request_get_size(ngx_http_request_t *r,
0024     ngx_http_variable_value_t *v, uintptr_t data);
0025 static void ngx_http_variable_request_set_size(ngx_http_request_t *r,
0026     ngx_http_variable_value_t *v, uintptr_t data);
0027 static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r,
0028     ngx_http_variable_value_t *v, uintptr_t data);
0029 
0030 static ngx_int_t ngx_http_variable_cookies(ngx_http_request_t *r,
0031     ngx_http_variable_value_t *v, uintptr_t data);
0032 static ngx_int_t ngx_http_variable_headers(ngx_http_request_t *r,
0033     ngx_http_variable_value_t *v, uintptr_t data);
0034 static ngx_int_t ngx_http_variable_headers_internal(ngx_http_request_t *r,
0035     ngx_http_variable_value_t *v, uintptr_t data, u_char sep);
0036 
0037 static ngx_int_t ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
0038     ngx_http_variable_value_t *v, uintptr_t data);
0039 static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
0040     ngx_http_variable_value_t *v, uintptr_t data);
0041 static ngx_int_t ngx_http_variable_unknown_trailer_out(ngx_http_request_t *r,
0042     ngx_http_variable_value_t *v, uintptr_t data);
0043 static ngx_int_t ngx_http_variable_request_line(ngx_http_request_t *r,
0044     ngx_http_variable_value_t *v, uintptr_t data);
0045 static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r,
0046     ngx_http_variable_value_t *v, uintptr_t data);
0047 static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r,
0048     ngx_http_variable_value_t *v, uintptr_t data);
0049 #if (NGX_HAVE_TCP_INFO)
0050 static ngx_int_t ngx_http_variable_tcpinfo(ngx_http_request_t *r,
0051     ngx_http_variable_value_t *v, uintptr_t data);
0052 #endif
0053 
0054 static ngx_int_t ngx_http_variable_content_length(ngx_http_request_t *r,
0055     ngx_http_variable_value_t *v, uintptr_t data);
0056 static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r,
0057     ngx_http_variable_value_t *v, uintptr_t data);
0058 static ngx_int_t ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
0059     ngx_http_variable_value_t *v, uintptr_t data);
0060 static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r,
0061     ngx_http_variable_value_t *v, uintptr_t data);
0062 static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r,
0063     ngx_http_variable_value_t *v, uintptr_t data);
0064 static ngx_int_t ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
0065     ngx_http_variable_value_t *v, uintptr_t data);
0066 static ngx_int_t ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
0067     ngx_http_variable_value_t *v, uintptr_t data);
0068 static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r,
0069     ngx_http_variable_value_t *v, uintptr_t data);
0070 static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
0071     ngx_http_variable_value_t *v, uintptr_t data);
0072 static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r,
0073     ngx_http_variable_value_t *v, uintptr_t data);
0074 static ngx_int_t ngx_http_variable_https(ngx_http_request_t *r,
0075     ngx_http_variable_value_t *v, uintptr_t data);
0076 static void ngx_http_variable_set_args(ngx_http_request_t *r,
0077     ngx_http_variable_value_t *v, uintptr_t data);
0078 static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r,
0079     ngx_http_variable_value_t *v, uintptr_t data);
0080 static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r,
0081     ngx_http_variable_value_t *v, uintptr_t data);
0082 static ngx_int_t ngx_http_variable_realpath_root(ngx_http_request_t *r,
0083     ngx_http_variable_value_t *v, uintptr_t data);
0084 static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r,
0085     ngx_http_variable_value_t *v, uintptr_t data);
0086 static ngx_int_t ngx_http_variable_server_name(ngx_http_request_t *r,
0087     ngx_http_variable_value_t *v, uintptr_t data);
0088 static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r,
0089     ngx_http_variable_value_t *v, uintptr_t data);
0090 static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r,
0091     ngx_http_variable_value_t *v, uintptr_t data);
0092 static ngx_int_t ngx_http_variable_bytes_sent(ngx_http_request_t *r,
0093     ngx_http_variable_value_t *v, uintptr_t data);
0094 static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
0095     ngx_http_variable_value_t *v, uintptr_t data);
0096 static ngx_int_t ngx_http_variable_pipe(ngx_http_request_t *r,
0097     ngx_http_variable_value_t *v, uintptr_t data);
0098 static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
0099     ngx_http_variable_value_t *v, uintptr_t data);
0100 static ngx_int_t ngx_http_variable_request_body(ngx_http_request_t *r,
0101     ngx_http_variable_value_t *v, uintptr_t data);
0102 static ngx_int_t ngx_http_variable_request_body_file(ngx_http_request_t *r,
0103     ngx_http_variable_value_t *v, uintptr_t data);
0104 static ngx_int_t ngx_http_variable_request_length(ngx_http_request_t *r,
0105     ngx_http_variable_value_t *v, uintptr_t data);
0106 static ngx_int_t ngx_http_variable_request_time(ngx_http_request_t *r,
0107     ngx_http_variable_value_t *v, uintptr_t data);
0108 static ngx_int_t ngx_http_variable_request_id(ngx_http_request_t *r,
0109     ngx_http_variable_value_t *v, uintptr_t data);
0110 static ngx_int_t ngx_http_variable_status(ngx_http_request_t *r,
0111     ngx_http_variable_value_t *v, uintptr_t data);
0112 
0113 static ngx_int_t ngx_http_variable_sent_content_type(ngx_http_request_t *r,
0114     ngx_http_variable_value_t *v, uintptr_t data);
0115 static ngx_int_t ngx_http_variable_sent_content_length(ngx_http_request_t *r,
0116     ngx_http_variable_value_t *v, uintptr_t data);
0117 static ngx_int_t ngx_http_variable_sent_location(ngx_http_request_t *r,
0118     ngx_http_variable_value_t *v, uintptr_t data);
0119 static ngx_int_t ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
0120     ngx_http_variable_value_t *v, uintptr_t data);
0121 static ngx_int_t ngx_http_variable_sent_connection(ngx_http_request_t *r,
0122     ngx_http_variable_value_t *v, uintptr_t data);
0123 static ngx_int_t ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
0124     ngx_http_variable_value_t *v, uintptr_t data);
0125 static ngx_int_t ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
0126     ngx_http_variable_value_t *v, uintptr_t data);
0127 
0128 static ngx_int_t ngx_http_variable_connection(ngx_http_request_t *r,
0129     ngx_http_variable_value_t *v, uintptr_t data);
0130 static ngx_int_t ngx_http_variable_connection_requests(ngx_http_request_t *r,
0131     ngx_http_variable_value_t *v, uintptr_t data);
0132 
0133 static ngx_int_t ngx_http_variable_nginx_version(ngx_http_request_t *r,
0134     ngx_http_variable_value_t *v, uintptr_t data);
0135 static ngx_int_t ngx_http_variable_hostname(ngx_http_request_t *r,
0136     ngx_http_variable_value_t *v, uintptr_t data);
0137 static ngx_int_t ngx_http_variable_pid(ngx_http_request_t *r,
0138     ngx_http_variable_value_t *v, uintptr_t data);
0139 static ngx_int_t ngx_http_variable_msec(ngx_http_request_t *r,
0140     ngx_http_variable_value_t *v, uintptr_t data);
0141 static ngx_int_t ngx_http_variable_time_iso8601(ngx_http_request_t *r,
0142     ngx_http_variable_value_t *v, uintptr_t data);
0143 static ngx_int_t ngx_http_variable_time_local(ngx_http_request_t *r,
0144     ngx_http_variable_value_t *v, uintptr_t data);
0145 
0146 /*
0147  * TODO:
0148  *     Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED
0149  *                 REMOTE_HOST (null), REMOTE_IDENT (null),
0150  *                 SERVER_SOFTWARE
0151  *
0152  *     Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner)
0153  */
0154 
0155 /*
0156  * the $http_host, $http_user_agent, $http_referer, and $http_via
0157  * variables may be handled by generic
0158  * ngx_http_variable_unknown_header_in(), but for performance reasons
0159  * they are handled using dedicated entries
0160  */
0161 
0162 static ngx_http_variable_t  ngx_http_core_variables[] = {
0163 
0164     { ngx_string("http_host"), NULL, ngx_http_variable_header,
0165       offsetof(ngx_http_request_t, headers_in.host), 0, 0 },
0166 
0167     { ngx_string("http_user_agent"), NULL, ngx_http_variable_header,
0168       offsetof(ngx_http_request_t, headers_in.user_agent), 0, 0 },
0169 
0170     { ngx_string("http_referer"), NULL, ngx_http_variable_header,
0171       offsetof(ngx_http_request_t, headers_in.referer), 0, 0 },
0172 
0173 #if (NGX_HTTP_GZIP)
0174     { ngx_string("http_via"), NULL, ngx_http_variable_header,
0175       offsetof(ngx_http_request_t, headers_in.via), 0, 0 },
0176 #endif
0177 
0178 #if (NGX_HTTP_X_FORWARDED_FOR)
0179     { ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_headers,
0180       offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 },
0181 #endif
0182 
0183     { ngx_string("http_cookie"), NULL, ngx_http_variable_cookies,
0184       offsetof(ngx_http_request_t, headers_in.cookies), 0, 0 },
0185 
0186     { ngx_string("content_length"), NULL, ngx_http_variable_content_length,
0187       0, 0, 0 },
0188 
0189     { ngx_string("content_type"), NULL, ngx_http_variable_header,
0190       offsetof(ngx_http_request_t, headers_in.content_type), 0, 0 },
0191 
0192     { ngx_string("host"), NULL, ngx_http_variable_host, 0, 0, 0 },
0193 
0194     { ngx_string("binary_remote_addr"), NULL,
0195       ngx_http_variable_binary_remote_addr, 0, 0, 0 },
0196 
0197     { ngx_string("remote_addr"), NULL, ngx_http_variable_remote_addr, 0, 0, 0 },
0198 
0199     { ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 },
0200 
0201     { ngx_string("proxy_protocol_addr"), NULL,
0202       ngx_http_variable_proxy_protocol_addr, 0, 0, 0 },
0203 
0204     { ngx_string("proxy_protocol_port"), NULL,
0205       ngx_http_variable_proxy_protocol_port, 0, 0, 0 },
0206 
0207     { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },
0208 
0209     { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 },
0210 
0211     { ngx_string("server_protocol"), NULL, ngx_http_variable_request,
0212       offsetof(ngx_http_request_t, http_protocol), 0, 0 },
0213 
0214     { ngx_string("scheme"), NULL, ngx_http_variable_scheme, 0, 0, 0 },
0215 
0216     { ngx_string("https"), NULL, ngx_http_variable_https, 0, 0, 0 },
0217 
0218     { ngx_string("request_uri"), NULL, ngx_http_variable_request,
0219       offsetof(ngx_http_request_t, unparsed_uri), 0, 0 },
0220 
0221     { ngx_string("uri"), NULL, ngx_http_variable_request,
0222       offsetof(ngx_http_request_t, uri),
0223       NGX_HTTP_VAR_NOCACHEABLE, 0 },
0224 
0225     { ngx_string("document_uri"), NULL, ngx_http_variable_request,
0226       offsetof(ngx_http_request_t, uri),
0227       NGX_HTTP_VAR_NOCACHEABLE, 0 },
0228 
0229     { ngx_string("request"), NULL, ngx_http_variable_request_line, 0, 0, 0 },
0230 
0231     { ngx_string("document_root"), NULL,
0232       ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
0233 
0234     { ngx_string("realpath_root"), NULL,
0235       ngx_http_variable_realpath_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
0236 
0237     { ngx_string("query_string"), NULL, ngx_http_variable_request,
0238       offsetof(ngx_http_request_t, args),
0239       NGX_HTTP_VAR_NOCACHEABLE, 0 },
0240 
0241     { ngx_string("args"),
0242       ngx_http_variable_set_args,
0243       ngx_http_variable_request,
0244       offsetof(ngx_http_request_t, args),
0245       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
0246 
0247     { ngx_string("is_args"), NULL, ngx_http_variable_is_args,
0248       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
0249 
0250     { ngx_string("request_filename"), NULL,
0251       ngx_http_variable_request_filename, 0,
0252       NGX_HTTP_VAR_NOCACHEABLE, 0 },
0253 
0254     { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 },
0255 
0256     { ngx_string("request_method"), NULL,
0257       ngx_http_variable_request_method, 0,
0258       NGX_HTTP_VAR_NOCACHEABLE, 0 },
0259 
0260     { ngx_string("remote_user"), NULL, ngx_http_variable_remote_user, 0, 0, 0 },
0261 
0262     { ngx_string("bytes_sent"), NULL, ngx_http_variable_bytes_sent,
0263       0, 0, 0 },
0264 
0265     { ngx_string("body_bytes_sent"), NULL, ngx_http_variable_body_bytes_sent,
0266       0, 0, 0 },
0267 
0268     { ngx_string("pipe"), NULL, ngx_http_variable_pipe,
0269       0, 0, 0 },
0270 
0271     { ngx_string("request_completion"), NULL,
0272       ngx_http_variable_request_completion,
0273       0, 0, 0 },
0274 
0275     { ngx_string("request_body"), NULL,
0276       ngx_http_variable_request_body,
0277       0, 0, 0 },
0278 
0279     { ngx_string("request_body_file"), NULL,
0280       ngx_http_variable_request_body_file,
0281       0, 0, 0 },
0282 
0283     { ngx_string("request_length"), NULL, ngx_http_variable_request_length,
0284       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
0285 
0286     { ngx_string("request_time"), NULL, ngx_http_variable_request_time,
0287       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
0288 
0289     { ngx_string("request_id"), NULL,
0290       ngx_http_variable_request_id,
0291       0, 0, 0 },
0292 
0293     { ngx_string("status"), NULL,
0294       ngx_http_variable_status, 0,
0295       NGX_HTTP_VAR_NOCACHEABLE, 0 },
0296 
0297     { ngx_string("sent_http_content_type"), NULL,
0298       ngx_http_variable_sent_content_type, 0, 0, 0 },
0299 
0300     { ngx_string("sent_http_content_length"), NULL,
0301       ngx_http_variable_sent_content_length, 0, 0, 0 },
0302 
0303     { ngx_string("sent_http_location"), NULL,
0304       ngx_http_variable_sent_location, 0, 0, 0 },
0305 
0306     { ngx_string("sent_http_last_modified"), NULL,
0307       ngx_http_variable_sent_last_modified, 0, 0, 0 },
0308 
0309     { ngx_string("sent_http_connection"), NULL,
0310       ngx_http_variable_sent_connection, 0, 0, 0 },
0311 
0312     { ngx_string("sent_http_keep_alive"), NULL,
0313       ngx_http_variable_sent_keep_alive, 0, 0, 0 },
0314 
0315     { ngx_string("sent_http_transfer_encoding"), NULL,
0316       ngx_http_variable_sent_transfer_encoding, 0, 0, 0 },
0317 
0318     { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers,
0319       offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 },
0320 
0321     { ngx_string("sent_http_link"), NULL, ngx_http_variable_headers,
0322       offsetof(ngx_http_request_t, headers_out.link), 0, 0 },
0323 
0324     { ngx_string("limit_rate"), ngx_http_variable_request_set_size,
0325       ngx_http_variable_request_get_size,
0326       offsetof(ngx_http_request_t, limit_rate),
0327       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
0328 
0329     { ngx_string("connection"), NULL,
0330       ngx_http_variable_connection, 0, 0, 0 },
0331 
0332     { ngx_string("connection_requests"), NULL,
0333       ngx_http_variable_connection_requests, 0, 0, 0 },
0334 
0335     { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version,
0336       0, 0, 0 },
0337 
0338     { ngx_string("hostname"), NULL, ngx_http_variable_hostname,
0339       0, 0, 0 },
0340 
0341     { ngx_string("pid"), NULL, ngx_http_variable_pid,
0342       0, 0, 0 },
0343 
0344     { ngx_string("msec"), NULL, ngx_http_variable_msec,
0345       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
0346 
0347     { ngx_string("time_iso8601"), NULL, ngx_http_variable_time_iso8601,
0348       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
0349 
0350     { ngx_string("time_local"), NULL, ngx_http_variable_time_local,
0351       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
0352 
0353 #if (NGX_HAVE_TCP_INFO)
0354     { ngx_string("tcpinfo_rtt"), NULL, ngx_http_variable_tcpinfo,
0355       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
0356 
0357     { ngx_string("tcpinfo_rttvar"), NULL, ngx_http_variable_tcpinfo,
0358       1, NGX_HTTP_VAR_NOCACHEABLE, 0 },
0359 
0360     { ngx_string("tcpinfo_snd_cwnd"), NULL, ngx_http_variable_tcpinfo,
0361       2, NGX_HTTP_VAR_NOCACHEABLE, 0 },
0362 
0363     { ngx_string("tcpinfo_rcv_space"), NULL, ngx_http_variable_tcpinfo,
0364       3, NGX_HTTP_VAR_NOCACHEABLE, 0 },
0365 #endif
0366 
0367     { ngx_string("http_"), NULL, ngx_http_variable_unknown_header_in,
0368       0, NGX_HTTP_VAR_PREFIX, 0 },
0369 
0370     { ngx_string("sent_http_"), NULL, ngx_http_variable_unknown_header_out,
0371       0, NGX_HTTP_VAR_PREFIX, 0 },
0372 
0373     { ngx_string("sent_trailer_"), NULL, ngx_http_variable_unknown_trailer_out,
0374       0, NGX_HTTP_VAR_PREFIX, 0 },
0375 
0376     { ngx_string("cookie_"), NULL, ngx_http_variable_cookie,
0377       0, NGX_HTTP_VAR_PREFIX, 0 },
0378 
0379     { ngx_string("arg_"), NULL, ngx_http_variable_argument,
0380       0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 },
0381 
0382       ngx_http_null_variable
0383 };
0384 
0385 
0386 ngx_http_variable_value_t  ngx_http_variable_null_value =
0387     ngx_http_variable("");
0388 ngx_http_variable_value_t  ngx_http_variable_true_value =
0389     ngx_http_variable("1");
0390 
0391 
0392 static ngx_uint_t  ngx_http_variable_depth = 100;
0393 
0394 
0395 ngx_http_variable_t *
0396 ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
0397 {
0398     ngx_int_t                   rc;
0399     ngx_uint_t                  i;
0400     ngx_hash_key_t             *key;
0401     ngx_http_variable_t        *v;
0402     ngx_http_core_main_conf_t  *cmcf;
0403 
0404     if (name->len == 0) {
0405         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0406                            "invalid variable name \"$\"");
0407         return NULL;
0408     }
0409 
0410     if (flags & NGX_HTTP_VAR_PREFIX) {
0411         return ngx_http_add_prefix_variable(cf, name, flags);
0412     }
0413 
0414     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
0415 
0416     key = cmcf->variables_keys->keys.elts;
0417     for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) {
0418         if (name->len != key[i].key.len
0419             || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0)
0420         {
0421             continue;
0422         }
0423 
0424         v = key[i].value;
0425 
0426         if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
0427             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0428                                "the duplicate \"%V\" variable", name);
0429             return NULL;
0430         }
0431 
0432         if (!(flags & NGX_HTTP_VAR_WEAK)) {
0433             v->flags &= ~NGX_HTTP_VAR_WEAK;
0434         }
0435 
0436         return v;
0437     }
0438 
0439     v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));
0440     if (v == NULL) {
0441         return NULL;
0442     }
0443 
0444     v->name.len = name->len;
0445     v->name.data = ngx_pnalloc(cf->pool, name->len);
0446     if (v->name.data == NULL) {
0447         return NULL;
0448     }
0449 
0450     ngx_strlow(v->name.data, name->data, name->len);
0451 
0452     v->set_handler = NULL;
0453     v->get_handler = NULL;
0454     v->data = 0;
0455     v->flags = flags;
0456     v->index = 0;
0457 
0458     rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0);
0459 
0460     if (rc == NGX_ERROR) {
0461         return NULL;
0462     }
0463 
0464     if (rc == NGX_BUSY) {
0465         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0466                            "conflicting variable name \"%V\"", name);
0467         return NULL;
0468     }
0469 
0470     return v;
0471 }
0472 
0473 
0474 static ngx_http_variable_t *
0475 ngx_http_add_prefix_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
0476 {
0477     ngx_uint_t                  i;
0478     ngx_http_variable_t        *v;
0479     ngx_http_core_main_conf_t  *cmcf;
0480 
0481     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
0482 
0483     v = cmcf->prefix_variables.elts;
0484     for (i = 0; i < cmcf->prefix_variables.nelts; i++) {
0485         if (name->len != v[i].name.len
0486             || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0)
0487         {
0488             continue;
0489         }
0490 
0491         v = &v[i];
0492 
0493         if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
0494             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0495                                "the duplicate \"%V\" variable", name);
0496             return NULL;
0497         }
0498 
0499         if (!(flags & NGX_HTTP_VAR_WEAK)) {
0500             v->flags &= ~NGX_HTTP_VAR_WEAK;
0501         }
0502 
0503         return v;
0504     }
0505 
0506     v = ngx_array_push(&cmcf->prefix_variables);
0507     if (v == NULL) {
0508         return NULL;
0509     }
0510 
0511     v->name.len = name->len;
0512     v->name.data = ngx_pnalloc(cf->pool, name->len);
0513     if (v->name.data == NULL) {
0514         return NULL;
0515     }
0516 
0517     ngx_strlow(v->name.data, name->data, name->len);
0518 
0519     v->set_handler = NULL;
0520     v->get_handler = NULL;
0521     v->data = 0;
0522     v->flags = flags;
0523     v->index = 0;
0524 
0525     return v;
0526 }
0527 
0528 
0529 ngx_int_t
0530 ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name)
0531 {
0532     ngx_uint_t                  i;
0533     ngx_http_variable_t        *v;
0534     ngx_http_core_main_conf_t  *cmcf;
0535 
0536     if (name->len == 0) {
0537         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0538                            "invalid variable name \"$\"");
0539         return NGX_ERROR;
0540     }
0541 
0542     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
0543 
0544     v = cmcf->variables.elts;
0545 
0546     if (v == NULL) {
0547         if (ngx_array_init(&cmcf->variables, cf->pool, 4,
0548                            sizeof(ngx_http_variable_t))
0549             != NGX_OK)
0550         {
0551             return NGX_ERROR;
0552         }
0553 
0554     } else {
0555         for (i = 0; i < cmcf->variables.nelts; i++) {
0556             if (name->len != v[i].name.len
0557                 || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0)
0558             {
0559                 continue;
0560             }
0561 
0562             return i;
0563         }
0564     }
0565 
0566     v = ngx_array_push(&cmcf->variables);
0567     if (v == NULL) {
0568         return NGX_ERROR;
0569     }
0570 
0571     v->name.len = name->len;
0572     v->name.data = ngx_pnalloc(cf->pool, name->len);
0573     if (v->name.data == NULL) {
0574         return NGX_ERROR;
0575     }
0576 
0577     ngx_strlow(v->name.data, name->data, name->len);
0578 
0579     v->set_handler = NULL;
0580     v->get_handler = NULL;
0581     v->data = 0;
0582     v->flags = 0;
0583     v->index = cmcf->variables.nelts - 1;
0584 
0585     return v->index;
0586 }
0587 
0588 
0589 ngx_http_variable_value_t *
0590 ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
0591 {
0592     ngx_http_variable_t        *v;
0593     ngx_http_core_main_conf_t  *cmcf;
0594 
0595     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
0596 
0597     if (cmcf->variables.nelts <= index) {
0598         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
0599                       "unknown variable index: %ui", index);
0600         return NULL;
0601     }
0602 
0603     if (r->variables[index].not_found || r->variables[index].valid) {
0604         return &r->variables[index];
0605     }
0606 
0607     v = cmcf->variables.elts;
0608 
0609     if (ngx_http_variable_depth == 0) {
0610         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
0611                       "cycle while evaluating variable \"%V\"",
0612                       &v[index].name);
0613         return NULL;
0614     }
0615 
0616     ngx_http_variable_depth--;
0617 
0618     if (v[index].get_handler(r, &r->variables[index], v[index].data)
0619         == NGX_OK)
0620     {
0621         ngx_http_variable_depth++;
0622 
0623         if (v[index].flags & NGX_HTTP_VAR_NOCACHEABLE) {
0624             r->variables[index].no_cacheable = 1;
0625         }
0626 
0627         return &r->variables[index];
0628     }
0629 
0630     ngx_http_variable_depth++;
0631 
0632     r->variables[index].valid = 0;
0633     r->variables[index].not_found = 1;
0634 
0635     return NULL;
0636 }
0637 
0638 
0639 ngx_http_variable_value_t *
0640 ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index)
0641 {
0642     ngx_http_variable_value_t  *v;
0643 
0644     v = &r->variables[index];
0645 
0646     if (v->valid || v->not_found) {
0647         if (!v->no_cacheable) {
0648             return v;
0649         }
0650 
0651         v->valid = 0;
0652         v->not_found = 0;
0653     }
0654 
0655     return ngx_http_get_indexed_variable(r, index);
0656 }
0657 
0658 
0659 ngx_http_variable_value_t *
0660 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
0661 {
0662     size_t                      len;
0663     ngx_uint_t                  i, n;
0664     ngx_http_variable_t        *v;
0665     ngx_http_variable_value_t  *vv;
0666     ngx_http_core_main_conf_t  *cmcf;
0667 
0668     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
0669 
0670     v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len);
0671 
0672     if (v) {
0673         if (v->flags & NGX_HTTP_VAR_INDEXED) {
0674             return ngx_http_get_flushed_variable(r, v->index);
0675         }
0676 
0677         if (ngx_http_variable_depth == 0) {
0678             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
0679                           "cycle while evaluating variable \"%V\"", name);
0680             return NULL;
0681         }
0682 
0683         ngx_http_variable_depth--;
0684 
0685         vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
0686 
0687         if (vv && v->get_handler(r, vv, v->data) == NGX_OK) {
0688             ngx_http_variable_depth++;
0689             return vv;
0690         }
0691 
0692         ngx_http_variable_depth++;
0693         return NULL;
0694     }
0695 
0696     vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
0697     if (vv == NULL) {
0698         return NULL;
0699     }
0700 
0701     len = 0;
0702 
0703     v = cmcf->prefix_variables.elts;
0704     n = cmcf->prefix_variables.nelts;
0705 
0706     for (i = 0; i < cmcf->prefix_variables.nelts; i++) {
0707         if (name->len >= v[i].name.len && name->len > len
0708             && ngx_strncmp(name->data, v[i].name.data, v[i].name.len) == 0)
0709         {
0710             len = v[i].name.len;
0711             n = i;
0712         }
0713     }
0714 
0715     if (n != cmcf->prefix_variables.nelts) {
0716         if (v[n].get_handler(r, vv, (uintptr_t) name) == NGX_OK) {
0717             return vv;
0718         }
0719 
0720         return NULL;
0721     }
0722 
0723     vv->not_found = 1;
0724 
0725     return vv;
0726 }
0727 
0728 
0729 static ngx_int_t
0730 ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v,
0731     uintptr_t data)
0732 {
0733     ngx_str_t  *s;
0734 
0735     s = (ngx_str_t *) ((char *) r + data);
0736 
0737     if (s->data) {
0738         v->len = s->len;
0739         v->valid = 1;
0740         v->no_cacheable = 0;
0741         v->not_found = 0;
0742         v->data = s->data;
0743 
0744     } else {
0745         v->not_found = 1;
0746     }
0747 
0748     return NGX_OK;
0749 }
0750 
0751 
0752 #if 0
0753 
0754 static void
0755 ngx_http_variable_request_set(ngx_http_request_t *r,
0756     ngx_http_variable_value_t *v, uintptr_t data)
0757 {
0758     ngx_str_t  *s;
0759 
0760     s = (ngx_str_t *) ((char *) r + data);
0761 
0762     s->len = v->len;
0763     s->data = v->data;
0764 }
0765 
0766 #endif
0767 
0768 
0769 static ngx_int_t
0770 ngx_http_variable_request_get_size(ngx_http_request_t *r,
0771     ngx_http_variable_value_t *v, uintptr_t data)
0772 {
0773     size_t  *sp;
0774 
0775     sp = (size_t *) ((char *) r + data);
0776 
0777     v->data = ngx_pnalloc(r->pool, NGX_SIZE_T_LEN);
0778     if (v->data == NULL) {
0779         return NGX_ERROR;
0780     }
0781 
0782     v->len = ngx_sprintf(v->data, "%uz", *sp) - v->data;
0783     v->valid = 1;
0784     v->no_cacheable = 0;
0785     v->not_found = 0;
0786 
0787     return NGX_OK;
0788 }
0789 
0790 
0791 static void
0792 ngx_http_variable_request_set_size(ngx_http_request_t *r,
0793     ngx_http_variable_value_t *v, uintptr_t data)
0794 {
0795     ssize_t    s, *sp;
0796     ngx_str_t  val;
0797 
0798     val.len = v->len;
0799     val.data = v->data;
0800 
0801     s = ngx_parse_size(&val);
0802 
0803     if (s == NGX_ERROR) {
0804         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
0805                       "invalid size \"%V\"", &val);
0806         return;
0807     }
0808 
0809     sp = (ssize_t *) ((char *) r + data);
0810 
0811     *sp = s;
0812 
0813     return;
0814 }
0815 
0816 
0817 static ngx_int_t
0818 ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v,
0819     uintptr_t data)
0820 {
0821     ngx_table_elt_t  *h;
0822 
0823     h = *(ngx_table_elt_t **) ((char *) r + data);
0824 
0825     if (h) {
0826         v->len = h->value.len;
0827         v->valid = 1;
0828         v->no_cacheable = 0;
0829         v->not_found = 0;
0830         v->data = h->value.data;
0831 
0832     } else {
0833         v->not_found = 1;
0834     }
0835 
0836     return NGX_OK;
0837 }
0838 
0839 
0840 static ngx_int_t
0841 ngx_http_variable_cookies(ngx_http_request_t *r,
0842     ngx_http_variable_value_t *v, uintptr_t data)
0843 {
0844     return ngx_http_variable_headers_internal(r, v, data, ';');
0845 }
0846 
0847 
0848 static ngx_int_t
0849 ngx_http_variable_headers(ngx_http_request_t *r,
0850     ngx_http_variable_value_t *v, uintptr_t data)
0851 {
0852     return ngx_http_variable_headers_internal(r, v, data, ',');
0853 }
0854 
0855 
0856 static ngx_int_t
0857 ngx_http_variable_headers_internal(ngx_http_request_t *r,
0858     ngx_http_variable_value_t *v, uintptr_t data, u_char sep)
0859 {
0860     size_t             len;
0861     u_char            *p, *end;
0862     ngx_uint_t         i, n;
0863     ngx_array_t       *a;
0864     ngx_table_elt_t  **h;
0865 
0866     a = (ngx_array_t *) ((char *) r + data);
0867 
0868     n = a->nelts;
0869     h = a->elts;
0870 
0871     len = 0;
0872 
0873     for (i = 0; i < n; i++) {
0874 
0875         if (h[i]->hash == 0) {
0876             continue;
0877         }
0878 
0879         len += h[i]->value.len + 2;
0880     }
0881 
0882     if (len == 0) {
0883         v->not_found = 1;
0884         return NGX_OK;
0885     }
0886 
0887     len -= 2;
0888 
0889     v->valid = 1;
0890     v->no_cacheable = 0;
0891     v->not_found = 0;
0892 
0893     if (n == 1) {
0894         v->len = (*h)->value.len;
0895         v->data = (*h)->value.data;
0896 
0897         return NGX_OK;
0898     }
0899 
0900     p = ngx_pnalloc(r->pool, len);
0901     if (p == NULL) {
0902         return NGX_ERROR;
0903     }
0904 
0905     v->len = len;
0906     v->data = p;
0907 
0908     end = p + len;
0909 
0910     for (i = 0; /* void */ ; i++) {
0911 
0912         if (h[i]->hash == 0) {
0913             continue;
0914         }
0915 
0916         p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
0917 
0918         if (p == end) {
0919             break;
0920         }
0921 
0922         *p++ = sep; *p++ = ' ';
0923     }
0924 
0925     return NGX_OK;
0926 }
0927 
0928 
0929 static ngx_int_t
0930 ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
0931     ngx_http_variable_value_t *v, uintptr_t data)
0932 {
0933     return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
0934                                             &r->headers_in.headers.part,
0935                                             sizeof("http_") - 1);
0936 }
0937 
0938 
0939 static ngx_int_t
0940 ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
0941     ngx_http_variable_value_t *v, uintptr_t data)
0942 {
0943     return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
0944                                             &r->headers_out.headers.part,
0945                                             sizeof("sent_http_") - 1);
0946 }
0947 
0948 
0949 static ngx_int_t
0950 ngx_http_variable_unknown_trailer_out(ngx_http_request_t *r,
0951     ngx_http_variable_value_t *v, uintptr_t data)
0952 {
0953     return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
0954                                             &r->headers_out.trailers.part,
0955                                             sizeof("sent_trailer_") - 1);
0956 }
0957 
0958 
0959 ngx_int_t
0960 ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var,
0961     ngx_list_part_t *part, size_t prefix)
0962 {
0963     u_char            ch;
0964     ngx_uint_t        i, n;
0965     ngx_table_elt_t  *header;
0966 
0967     header = part->elts;
0968 
0969     for (i = 0; /* void */ ; i++) {
0970 
0971         if (i >= part->nelts) {
0972             if (part->next == NULL) {
0973                 break;
0974             }
0975 
0976             part = part->next;
0977             header = part->elts;
0978             i = 0;
0979         }
0980 
0981         if (header[i].hash == 0) {
0982             continue;
0983         }
0984 
0985         for (n = 0; n + prefix < var->len && n < header[i].key.len; n++) {
0986             ch = header[i].key.data[n];
0987 
0988             if (ch >= 'A' && ch <= 'Z') {
0989                 ch |= 0x20;
0990 
0991             } else if (ch == '-') {
0992                 ch = '_';
0993             }
0994 
0995             if (var->data[n + prefix] != ch) {
0996                 break;
0997             }
0998         }
0999 
1000         if (n + prefix == var->len && n == header[i].key.len) {
1001             v->len = header[i].value.len;
1002             v->valid = 1;
1003             v->no_cacheable = 0;
1004             v->not_found = 0;
1005             v->data = header[i].value.data;
1006 
1007             return NGX_OK;
1008         }
1009     }
1010 
1011     v->not_found = 1;
1012 
1013     return NGX_OK;
1014 }
1015 
1016 
1017 static ngx_int_t
1018 ngx_http_variable_request_line(ngx_http_request_t *r,
1019     ngx_http_variable_value_t *v, uintptr_t data)
1020 {
1021     u_char  *p, *s;
1022 
1023     s = r->request_line.data;
1024 
1025     if (s == NULL) {
1026         s = r->request_start;
1027 
1028         if (s == NULL) {
1029             v->not_found = 1;
1030             return NGX_OK;
1031         }
1032 
1033         for (p = s; p < r->header_in->last; p++) {
1034             if (*p == CR || *p == LF) {
1035                 break;
1036             }
1037         }
1038 
1039         r->request_line.len = p - s;
1040         r->request_line.data = s;
1041     }
1042 
1043     v->len = r->request_line.len;
1044     v->valid = 1;
1045     v->no_cacheable = 0;
1046     v->not_found = 0;
1047     v->data = s;
1048 
1049     return NGX_OK;
1050 }
1051 
1052 
1053 static ngx_int_t
1054 ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v,
1055     uintptr_t data)
1056 {
1057     ngx_str_t *name = (ngx_str_t *) data;
1058 
1059     ngx_str_t  cookie, s;
1060 
1061     s.len = name->len - (sizeof("cookie_") - 1);
1062     s.data = name->data + sizeof("cookie_") - 1;
1063 
1064     if (ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &s, &cookie)
1065         == NGX_DECLINED)
1066     {
1067         v->not_found = 1;
1068         return NGX_OK;
1069     }
1070 
1071     v->len = cookie.len;
1072     v->valid = 1;
1073     v->no_cacheable = 0;
1074     v->not_found = 0;
1075     v->data = cookie.data;
1076 
1077     return NGX_OK;
1078 }
1079 
1080 
1081 static ngx_int_t
1082 ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v,
1083     uintptr_t data)
1084 {
1085     ngx_str_t *name = (ngx_str_t *) data;
1086 
1087     u_char     *arg;
1088     size_t      len;
1089     ngx_str_t   value;
1090 
1091     len = name->len - (sizeof("arg_") - 1);
1092     arg = name->data + sizeof("arg_") - 1;
1093 
1094     if (ngx_http_arg(r, arg, len, &value) != NGX_OK) {
1095         v->not_found = 1;
1096         return NGX_OK;
1097     }
1098 
1099     v->data = value.data;
1100     v->len = value.len;
1101     v->valid = 1;
1102     v->no_cacheable = 0;
1103     v->not_found = 0;
1104 
1105     return NGX_OK;
1106 }
1107 
1108 
1109 #if (NGX_HAVE_TCP_INFO)
1110 
1111 static ngx_int_t
1112 ngx_http_variable_tcpinfo(ngx_http_request_t *r, ngx_http_variable_value_t *v,
1113     uintptr_t data)
1114 {
1115     struct tcp_info  ti;
1116     socklen_t        len;
1117     uint32_t         value;
1118 
1119     len = sizeof(struct tcp_info);
1120     if (getsockopt(r->connection->fd, IPPROTO_TCP, TCP_INFO, &ti, &len) == -1) {
1121         v->not_found = 1;
1122         return NGX_OK;
1123     }
1124 
1125     v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN);
1126     if (v->data == NULL) {
1127         return NGX_ERROR;
1128     }
1129 
1130     switch (data) {
1131     case 0:
1132         value = ti.tcpi_rtt;
1133         break;
1134 
1135     case 1:
1136         value = ti.tcpi_rttvar;
1137         break;
1138 
1139     case 2:
1140         value = ti.tcpi_snd_cwnd;
1141         break;
1142 
1143     case 3:
1144         value = ti.tcpi_rcv_space;
1145         break;
1146 
1147     /* suppress warning */
1148     default:
1149         value = 0;
1150         break;
1151     }
1152 
1153     v->len = ngx_sprintf(v->data, "%uD", value) - v->data;
1154     v->valid = 1;
1155     v->no_cacheable = 0;
1156     v->not_found = 0;
1157 
1158     return NGX_OK;
1159 }
1160 
1161 #endif
1162 
1163 
1164 static ngx_int_t
1165 ngx_http_variable_content_length(ngx_http_request_t *r,
1166     ngx_http_variable_value_t *v, uintptr_t data)
1167 {
1168     u_char  *p;
1169 
1170     if (r->headers_in.content_length) {
1171         v->len = r->headers_in.content_length->value.len;
1172         v->data = r->headers_in.content_length->value.data;
1173         v->valid = 1;
1174         v->no_cacheable = 0;
1175         v->not_found = 0;
1176 
1177     } else if (r->reading_body) {
1178         v->not_found = 1;
1179         v->no_cacheable = 1;
1180 
1181     } else if (r->headers_in.content_length_n >= 0) {
1182         p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
1183         if (p == NULL) {
1184             return NGX_ERROR;
1185         }
1186 
1187         v->len = ngx_sprintf(p, "%O", r->headers_in.content_length_n) - p;
1188         v->data = p;
1189         v->valid = 1;
1190         v->no_cacheable = 0;
1191         v->not_found = 0;
1192 
1193     } else {
1194         v->not_found = 1;
1195     }
1196 
1197     return NGX_OK;
1198 }
1199 
1200 
1201 static ngx_int_t
1202 ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v,
1203     uintptr_t data)
1204 {
1205     ngx_http_core_srv_conf_t  *cscf;
1206 
1207     if (r->headers_in.server.len) {
1208         v->len = r->headers_in.server.len;
1209         v->data = r->headers_in.server.data;
1210 
1211     } else {
1212         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1213 
1214         v->len = cscf->server_name.len;
1215         v->data = cscf->server_name.data;
1216     }
1217 
1218     v->valid = 1;
1219     v->no_cacheable = 0;
1220     v->not_found = 0;
1221 
1222     return NGX_OK;
1223 }
1224 
1225 
1226 static ngx_int_t
1227 ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
1228     ngx_http_variable_value_t *v, uintptr_t data)
1229 {
1230     struct sockaddr_in   *sin;
1231 #if (NGX_HAVE_INET6)
1232     struct sockaddr_in6  *sin6;
1233 #endif
1234 
1235     switch (r->connection->sockaddr->sa_family) {
1236 
1237 #if (NGX_HAVE_INET6)
1238     case AF_INET6:
1239         sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
1240 
1241         v->len = sizeof(struct in6_addr);
1242         v->valid = 1;
1243         v->no_cacheable = 0;
1244         v->not_found = 0;
1245         v->data = sin6->sin6_addr.s6_addr;
1246 
1247         break;
1248 #endif
1249 
1250 #if (NGX_HAVE_UNIX_DOMAIN)
1251     case AF_UNIX:
1252 
1253         v->len = r->connection->addr_text.len;
1254         v->valid = 1;
1255         v->no_cacheable = 0;
1256         v->not_found = 0;
1257         v->data = r->connection->addr_text.data;
1258 
1259         break;
1260 #endif
1261 
1262     default: /* AF_INET */
1263         sin = (struct sockaddr_in *) r->connection->sockaddr;
1264 
1265         v->len = sizeof(in_addr_t);
1266         v->valid = 1;
1267         v->no_cacheable = 0;
1268         v->not_found = 0;
1269         v->data = (u_char *) &sin->sin_addr;
1270 
1271         break;
1272     }
1273 
1274     return NGX_OK;
1275 }
1276 
1277 
1278 static ngx_int_t
1279 ngx_http_variable_remote_addr(ngx_http_request_t *r,
1280     ngx_http_variable_value_t *v, uintptr_t data)
1281 {
1282     v->len = r->connection->addr_text.len;
1283     v->valid = 1;
1284     v->no_cacheable = 0;
1285     v->not_found = 0;
1286     v->data = r->connection->addr_text.data;
1287 
1288     return NGX_OK;
1289 }
1290 
1291 
1292 static ngx_int_t
1293 ngx_http_variable_remote_port(ngx_http_request_t *r,
1294     ngx_http_variable_value_t *v, uintptr_t data)
1295 {
1296     ngx_uint_t  port;
1297 
1298     v->len = 0;
1299     v->valid = 1;
1300     v->no_cacheable = 0;
1301     v->not_found = 0;
1302 
1303     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
1304     if (v->data == NULL) {
1305         return NGX_ERROR;
1306     }
1307 
1308     port = ngx_inet_get_port(r->connection->sockaddr);
1309 
1310     if (port > 0 && port < 65536) {
1311         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
1312     }
1313 
1314     return NGX_OK;
1315 }
1316 
1317 
1318 static ngx_int_t
1319 ngx_http_variable_proxy_protocol_addr(ngx_http_request_t *r,
1320     ngx_http_variable_value_t *v, uintptr_t data)
1321 {
1322     v->len = r->connection->proxy_protocol_addr.len;
1323     v->valid = 1;
1324     v->no_cacheable = 0;
1325     v->not_found = 0;
1326     v->data = r->connection->proxy_protocol_addr.data;
1327 
1328     return NGX_OK;
1329 }
1330 
1331 
1332 static ngx_int_t
1333 ngx_http_variable_proxy_protocol_port(ngx_http_request_t *r,
1334     ngx_http_variable_value_t *v, uintptr_t data)
1335 {
1336     ngx_uint_t  port;
1337 
1338     v->len = 0;
1339     v->valid = 1;
1340     v->no_cacheable = 0;
1341     v->not_found = 0;
1342 
1343     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
1344     if (v->data == NULL) {
1345         return NGX_ERROR;
1346     }
1347 
1348     port = r->connection->proxy_protocol_port;
1349 
1350     if (port > 0 && port < 65536) {
1351         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
1352     }
1353 
1354     return NGX_OK;
1355 }
1356 
1357 
1358 static ngx_int_t
1359 ngx_http_variable_server_addr(ngx_http_request_t *r,
1360     ngx_http_variable_value_t *v, uintptr_t data)
1361 {
1362     ngx_str_t  s;
1363     u_char     addr[NGX_SOCKADDR_STRLEN];
1364 
1365     s.len = NGX_SOCKADDR_STRLEN;
1366     s.data = addr;
1367 
1368     if (ngx_connection_local_sockaddr(r->connection, &s, 0) != NGX_OK) {
1369         return NGX_ERROR;
1370     }
1371 
1372     s.data = ngx_pnalloc(r->pool, s.len);
1373     if (s.data == NULL) {
1374         return NGX_ERROR;
1375     }
1376 
1377     ngx_memcpy(s.data, addr, s.len);
1378 
1379     v->len = s.len;
1380     v->valid = 1;
1381     v->no_cacheable = 0;
1382     v->not_found = 0;
1383     v->data = s.data;
1384 
1385     return NGX_OK;
1386 }
1387 
1388 
1389 static ngx_int_t
1390 ngx_http_variable_server_port(ngx_http_request_t *r,
1391     ngx_http_variable_value_t *v, uintptr_t data)
1392 {
1393     ngx_uint_t  port;
1394 
1395     v->len = 0;
1396     v->valid = 1;
1397     v->no_cacheable = 0;
1398     v->not_found = 0;
1399 
1400     if (ngx_connection_local_sockaddr(r->connection, NULL, 0) != NGX_OK) {
1401         return NGX_ERROR;
1402     }
1403 
1404     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
1405     if (v->data == NULL) {
1406         return NGX_ERROR;
1407     }
1408 
1409     port = ngx_inet_get_port(r->connection->local_sockaddr);
1410 
1411     if (port > 0 && port < 65536) {
1412         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
1413     }
1414 
1415     return NGX_OK;
1416 }
1417 
1418 
1419 static ngx_int_t
1420 ngx_http_variable_scheme(ngx_http_request_t *r,
1421     ngx_http_variable_value_t *v, uintptr_t data)
1422 {
1423 #if (NGX_HTTP_SSL)
1424 
1425     if (r->connection->ssl) {
1426         v->len = sizeof("https") - 1;
1427         v->valid = 1;
1428         v->no_cacheable = 0;
1429         v->not_found = 0;
1430         v->data = (u_char *) "https";
1431 
1432         return NGX_OK;
1433     }
1434 
1435 #endif
1436 
1437     v->len = sizeof("http") - 1;
1438     v->valid = 1;
1439     v->no_cacheable = 0;
1440     v->not_found = 0;
1441     v->data = (u_char *) "http";
1442 
1443     return NGX_OK;
1444 }
1445 
1446 
1447 static ngx_int_t
1448 ngx_http_variable_https(ngx_http_request_t *r,
1449     ngx_http_variable_value_t *v, uintptr_t data)
1450 {
1451 #if (NGX_HTTP_SSL)
1452 
1453     if (r->connection->ssl) {
1454         v->len = sizeof("on") - 1;
1455         v->valid = 1;
1456         v->no_cacheable = 0;
1457         v->not_found = 0;
1458         v->data = (u_char *) "on";
1459 
1460         return NGX_OK;
1461     }
1462 
1463 #endif
1464 
1465     *v = ngx_http_variable_null_value;
1466 
1467     return NGX_OK;
1468 }
1469 
1470 
1471 static void
1472 ngx_http_variable_set_args(ngx_http_request_t *r,
1473     ngx_http_variable_value_t *v, uintptr_t data)
1474 {
1475     r->args.len = v->len;
1476     r->args.data = v->data;
1477     r->valid_unparsed_uri = 0;
1478 }
1479 
1480 
1481 static ngx_int_t
1482 ngx_http_variable_is_args(ngx_http_request_t *r,
1483     ngx_http_variable_value_t *v, uintptr_t data)
1484 {
1485     if (r->args.len == 0) {
1486         *v = ngx_http_variable_null_value;
1487         return NGX_OK;
1488     }
1489 
1490     v->len = 1;
1491     v->valid = 1;
1492     v->no_cacheable = 0;
1493     v->not_found = 0;
1494     v->data = (u_char *) "?";
1495 
1496     return NGX_OK;
1497 }
1498 
1499 
1500 static ngx_int_t
1501 ngx_http_variable_document_root(ngx_http_request_t *r,
1502     ngx_http_variable_value_t *v, uintptr_t data)
1503 {
1504     ngx_str_t                  path;
1505     ngx_http_core_loc_conf_t  *clcf;
1506 
1507     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1508 
1509     if (clcf->root_lengths == NULL) {
1510         v->len = clcf->root.len;
1511         v->valid = 1;
1512         v->no_cacheable = 0;
1513         v->not_found = 0;
1514         v->data = clcf->root.data;
1515 
1516     } else {
1517         if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 0,
1518                                 clcf->root_values->elts)
1519             == NULL)
1520         {
1521             return NGX_ERROR;
1522         }
1523 
1524         if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, &path)
1525             != NGX_OK)
1526         {
1527             return NGX_ERROR;
1528         }
1529 
1530         v->len = path.len;
1531         v->valid = 1;
1532         v->no_cacheable = 0;
1533         v->not_found = 0;
1534         v->data = path.data;
1535     }
1536 
1537     return NGX_OK;
1538 }
1539 
1540 
1541 static ngx_int_t
1542 ngx_http_variable_realpath_root(ngx_http_request_t *r,
1543     ngx_http_variable_value_t *v, uintptr_t data)
1544 {
1545     u_char                    *real;
1546     size_t                     len;
1547     ngx_str_t                  path;
1548     ngx_http_core_loc_conf_t  *clcf;
1549 #if (NGX_HAVE_MAX_PATH)
1550     u_char                     buffer[NGX_MAX_PATH];
1551 #endif
1552 
1553     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1554 
1555     if (clcf->root_lengths == NULL) {
1556         path = clcf->root;
1557 
1558     } else {
1559         if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 1,
1560                                 clcf->root_values->elts)
1561             == NULL)
1562         {
1563             return NGX_ERROR;
1564         }
1565 
1566         path.data[path.len - 1] = '\0';
1567 
1568         if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, &path)
1569             != NGX_OK)
1570         {
1571             return NGX_ERROR;
1572         }
1573     }
1574 
1575 #if (NGX_HAVE_MAX_PATH)
1576     real = buffer;
1577 #else
1578     real = NULL;
1579 #endif
1580 
1581     real = ngx_realpath(path.data, real);
1582 
1583     if (real == NULL) {
1584         ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
1585                       ngx_realpath_n " \"%s\" failed", path.data);
1586         return NGX_ERROR;
1587     }
1588 
1589     len = ngx_strlen(real);
1590 
1591     v->data = ngx_pnalloc(r->pool, len);
1592     if (v->data == NULL) {
1593 #if !(NGX_HAVE_MAX_PATH)
1594         ngx_free(real);
1595 #endif
1596         return NGX_ERROR;
1597     }
1598 
1599     v->len = len;
1600     v->valid = 1;
1601     v->no_cacheable = 0;
1602     v->not_found = 0;
1603 
1604     ngx_memcpy(v->data, real, len);
1605 
1606 #if !(NGX_HAVE_MAX_PATH)
1607     ngx_free(real);
1608 #endif
1609 
1610     return NGX_OK;
1611 }
1612 
1613 
1614 static ngx_int_t
1615 ngx_http_variable_request_filename(ngx_http_request_t *r,
1616     ngx_http_variable_value_t *v, uintptr_t data)
1617 {
1618     size_t     root;
1619     ngx_str_t  path;
1620 
1621     if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
1622         return NGX_ERROR;
1623     }
1624 
1625     /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */
1626 
1627     v->len = path.len - 1;
1628     v->valid = 1;
1629     v->no_cacheable = 0;
1630     v->not_found = 0;
1631     v->data = path.data;
1632 
1633     return NGX_OK;
1634 }
1635 
1636 
1637 static ngx_int_t
1638 ngx_http_variable_server_name(ngx_http_request_t *r,
1639     ngx_http_variable_value_t *v, uintptr_t data)
1640 {
1641     ngx_http_core_srv_conf_t  *cscf;
1642 
1643     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1644 
1645     v->len = cscf->server_name.len;
1646     v->valid = 1;
1647     v->no_cacheable = 0;
1648     v->not_found = 0;
1649     v->data = cscf->server_name.data;
1650 
1651     return NGX_OK;
1652 }
1653 
1654 
1655 static ngx_int_t
1656 ngx_http_variable_request_method(ngx_http_request_t *r,
1657     ngx_http_variable_value_t *v, uintptr_t data)
1658 {
1659     if (r->main->method_name.data) {
1660         v->len = r->main->method_name.len;
1661         v->valid = 1;
1662         v->no_cacheable = 0;
1663         v->not_found = 0;
1664         v->data = r->main->method_name.data;
1665 
1666     } else {
1667         v->not_found = 1;
1668     }
1669 
1670     return NGX_OK;
1671 }
1672 
1673 
1674 static ngx_int_t
1675 ngx_http_variable_remote_user(ngx_http_request_t *r,
1676     ngx_http_variable_value_t *v, uintptr_t data)
1677 {
1678     ngx_int_t  rc;
1679 
1680     rc = ngx_http_auth_basic_user(r);
1681 
1682     if (rc == NGX_DECLINED) {
1683         v->not_found = 1;
1684         return NGX_OK;
1685     }
1686 
1687     if (rc == NGX_ERROR) {
1688         return NGX_ERROR;
1689     }
1690 
1691     v->len = r->headers_in.user.len;
1692     v->valid = 1;
1693     v->no_cacheable = 0;
1694     v->not_found = 0;
1695     v->data = r->headers_in.user.data;
1696 
1697     return NGX_OK;
1698 }
1699 
1700 
1701 static ngx_int_t
1702 ngx_http_variable_bytes_sent(ngx_http_request_t *r,
1703     ngx_http_variable_value_t *v, uintptr_t data)
1704 {
1705     u_char  *p;
1706 
1707     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
1708     if (p == NULL) {
1709         return NGX_ERROR;
1710     }
1711 
1712     v->len = ngx_sprintf(p, "%O", r->connection->sent) - p;
1713     v->valid = 1;
1714     v->no_cacheable = 0;
1715     v->not_found = 0;
1716     v->data = p;
1717 
1718     return NGX_OK;
1719 }
1720 
1721 
1722 static ngx_int_t
1723 ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
1724     ngx_http_variable_value_t *v, uintptr_t data)
1725 {
1726     off_t    sent;
1727     u_char  *p;
1728 
1729     sent = r->connection->sent - r->header_size;
1730 
1731     if (sent < 0) {
1732         sent = 0;
1733     }
1734 
1735     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
1736     if (p == NULL) {
1737         return NGX_ERROR;
1738     }
1739 
1740     v->len = ngx_sprintf(p, "%O", sent) - p;
1741     v->valid = 1;
1742     v->no_cacheable = 0;
1743     v->not_found = 0;
1744     v->data = p;
1745 
1746     return NGX_OK;
1747 }
1748 
1749 
1750 static ngx_int_t
1751 ngx_http_variable_pipe(ngx_http_request_t *r,
1752     ngx_http_variable_value_t *v, uintptr_t data)
1753 {
1754     v->data = (u_char *) (r->pipeline ? "p" : ".");
1755     v->len = 1;
1756     v->valid = 1;
1757     v->no_cacheable = 0;
1758     v->not_found = 0;
1759 
1760     return NGX_OK;
1761 }
1762 
1763 
1764 static ngx_int_t
1765 ngx_http_variable_status(ngx_http_request_t *r,
1766     ngx_http_variable_value_t *v, uintptr_t data)
1767 {
1768     ngx_uint_t  status;
1769 
1770     v->data = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
1771     if (v->data == NULL) {
1772         return NGX_ERROR;
1773     }
1774 
1775     if (r->err_status) {
1776         status = r->err_status;
1777 
1778     } else if (r->headers_out.status) {
1779         status = r->headers_out.status;
1780 
1781     } else if (r->http_version == NGX_HTTP_VERSION_9) {
1782         status = 9;
1783 
1784     } else {
1785         status = 0;
1786     }
1787 
1788     v->len = ngx_sprintf(v->data, "%03ui", status) - v->data;
1789     v->valid = 1;
1790     v->no_cacheable = 0;
1791     v->not_found = 0;
1792 
1793     return NGX_OK;
1794 }
1795 
1796 
1797 static ngx_int_t
1798 ngx_http_variable_sent_content_type(ngx_http_request_t *r,
1799     ngx_http_variable_value_t *v, uintptr_t data)
1800 {
1801     if (r->headers_out.content_type.len) {
1802         v->len = r->headers_out.content_type.len;
1803         v->valid = 1;
1804         v->no_cacheable = 0;
1805         v->not_found = 0;
1806         v->data = r->headers_out.content_type.data;
1807 
1808     } else {
1809         v->not_found = 1;
1810     }
1811 
1812     return NGX_OK;
1813 }
1814 
1815 
1816 static ngx_int_t
1817 ngx_http_variable_sent_content_length(ngx_http_request_t *r,
1818     ngx_http_variable_value_t *v, uintptr_t data)
1819 {
1820     u_char  *p;
1821 
1822     if (r->headers_out.content_length) {
1823         v->len = r->headers_out.content_length->value.len;
1824         v->valid = 1;
1825         v->no_cacheable = 0;
1826         v->not_found = 0;
1827         v->data = r->headers_out.content_length->value.data;
1828 
1829         return NGX_OK;
1830     }
1831 
1832     if (r->headers_out.content_length_n >= 0) {
1833         p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
1834         if (p == NULL) {
1835             return NGX_ERROR;
1836         }
1837 
1838         v->len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) - p;
1839         v->valid = 1;
1840         v->no_cacheable = 0;
1841         v->not_found = 0;
1842         v->data = p;
1843 
1844         return NGX_OK;
1845     }
1846 
1847     v->not_found = 1;
1848 
1849     return NGX_OK;
1850 }
1851 
1852 
1853 static ngx_int_t
1854 ngx_http_variable_sent_location(ngx_http_request_t *r,
1855     ngx_http_variable_value_t *v, uintptr_t data)
1856 {
1857     ngx_str_t  name;
1858 
1859     if (r->headers_out.location) {
1860         v->len = r->headers_out.location->value.len;
1861         v->valid = 1;
1862         v->no_cacheable = 0;
1863         v->not_found = 0;
1864         v->data = r->headers_out.location->value.data;
1865 
1866         return NGX_OK;
1867     }
1868 
1869     ngx_str_set(&name, "sent_http_location");
1870 
1871     return ngx_http_variable_unknown_header(v, &name,
1872                                             &r->headers_out.headers.part,
1873                                             sizeof("sent_http_") - 1);
1874 }
1875 
1876 
1877 static ngx_int_t
1878 ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
1879     ngx_http_variable_value_t *v, uintptr_t data)
1880 {
1881     u_char  *p;
1882 
1883     if (r->headers_out.last_modified) {
1884         v->len = r->headers_out.last_modified->value.len;
1885         v->valid = 1;
1886         v->no_cacheable = 0;
1887         v->not_found = 0;
1888         v->data = r->headers_out.last_modified->value.data;
1889 
1890         return NGX_OK;
1891     }
1892 
1893     if (r->headers_out.last_modified_time >= 0) {
1894         p = ngx_pnalloc(r->pool, sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1);
1895         if (p == NULL) {
1896             return NGX_ERROR;
1897         }
1898 
1899         v->len = ngx_http_time(p, r->headers_out.last_modified_time) - p;
1900         v->valid = 1;
1901         v->no_cacheable = 0;
1902         v->not_found = 0;
1903         v->data = p;
1904 
1905         return NGX_OK;
1906     }
1907 
1908     v->not_found = 1;
1909 
1910     return NGX_OK;
1911 }
1912 
1913 
1914 static ngx_int_t
1915 ngx_http_variable_sent_connection(ngx_http_request_t *r,
1916     ngx_http_variable_value_t *v, uintptr_t data)
1917 {
1918     size_t   len;
1919     char    *p;
1920 
1921     if (r->headers_out.status == NGX_HTTP_SWITCHING_PROTOCOLS) {
1922         len = sizeof("upgrade") - 1;
1923         p = "upgrade";
1924 
1925     } else if (r->keepalive) {
1926         len = sizeof("keep-alive") - 1;
1927         p = "keep-alive";
1928 
1929     } else {
1930         len = sizeof("close") - 1;
1931         p = "close";
1932     }
1933 
1934     v->len = len;
1935     v->valid = 1;
1936     v->no_cacheable = 0;
1937     v->not_found = 0;
1938     v->data = (u_char *) p;
1939 
1940     return NGX_OK;
1941 }
1942 
1943 
1944 static ngx_int_t
1945 ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
1946     ngx_http_variable_value_t *v, uintptr_t data)
1947 {
1948     u_char                    *p;
1949     ngx_http_core_loc_conf_t  *clcf;
1950 
1951     if (r->keepalive) {
1952         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1953 
1954         if (clcf->keepalive_header) {
1955 
1956             p = ngx_pnalloc(r->pool, sizeof("timeout=") - 1 + NGX_TIME_T_LEN);
1957             if (p == NULL) {
1958                 return NGX_ERROR;
1959             }
1960 
1961             v->len = ngx_sprintf(p, "timeout=%T", clcf->keepalive_header) - p;
1962             v->valid = 1;
1963             v->no_cacheable = 0;
1964             v->not_found = 0;
1965             v->data = p;
1966 
1967             return NGX_OK;
1968         }
1969     }
1970 
1971     v->not_found = 1;
1972 
1973     return NGX_OK;
1974 }
1975 
1976 
1977 static ngx_int_t
1978 ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
1979     ngx_http_variable_value_t *v, uintptr_t data)
1980 {
1981     if (r->chunked) {
1982         v->len = sizeof("chunked") - 1;
1983         v->valid = 1;
1984         v->no_cacheable = 0;
1985         v->not_found = 0;
1986         v->data = (u_char *) "chunked";
1987 
1988     } else {
1989         v->not_found = 1;
1990     }
1991 
1992     return NGX_OK;
1993 }
1994 
1995 
1996 static ngx_int_t
1997 ngx_http_variable_request_completion(ngx_http_request_t *r,
1998     ngx_http_variable_value_t *v, uintptr_t data)
1999 {
2000     if (r->request_complete) {
2001         v->len = 2;
2002         v->valid = 1;
2003         v->no_cacheable = 0;
2004         v->not_found = 0;
2005         v->data = (u_char *) "OK";
2006 
2007         return NGX_OK;
2008     }
2009 
2010     *v = ngx_http_variable_null_value;
2011 
2012     return NGX_OK;
2013 }
2014 
2015 
2016 static ngx_int_t
2017 ngx_http_variable_request_body(ngx_http_request_t *r,
2018     ngx_http_variable_value_t *v, uintptr_t data)
2019 {
2020     u_char       *p;
2021     size_t        len;
2022     ngx_buf_t    *buf;
2023     ngx_chain_t  *cl;
2024 
2025     if (r->request_body == NULL
2026         || r->request_body->bufs == NULL
2027         || r->request_body->temp_file)
2028     {
2029         v->not_found = 1;
2030 
2031         return NGX_OK;
2032     }
2033 
2034     cl = r->request_body->bufs;
2035     buf = cl->buf;
2036 
2037     if (cl->next == NULL) {
2038         v->len = buf->last - buf->pos;
2039         v->valid = 1;
2040         v->no_cacheable = 0;
2041         v->not_found = 0;
2042         v->data = buf->pos;
2043 
2044         return NGX_OK;
2045     }
2046 
2047     len = buf->last - buf->pos;
2048     cl = cl->next;
2049 
2050     for ( /* void */ ; cl; cl = cl->next) {
2051         buf = cl->buf;
2052         len += buf->last - buf->pos;
2053     }
2054 
2055     p = ngx_pnalloc(r->pool, len);
2056     if (p == NULL) {
2057         return NGX_ERROR;
2058     }
2059 
2060     v->data = p;
2061     cl = r->request_body->bufs;
2062 
2063     for ( /* void */ ; cl; cl = cl->next) {
2064         buf = cl->buf;
2065         p = ngx_cpymem(p, buf->pos, buf->last - buf->pos);
2066     }
2067 
2068     v->len = len;
2069     v->valid = 1;
2070     v->no_cacheable = 0;
2071     v->not_found = 0;
2072 
2073     return NGX_OK;
2074 }
2075 
2076 
2077 static ngx_int_t
2078 ngx_http_variable_request_body_file(ngx_http_request_t *r,
2079     ngx_http_variable_value_t *v, uintptr_t data)
2080 {
2081     if (r->request_body == NULL || r->request_body->temp_file == NULL) {
2082         v->not_found = 1;
2083 
2084         return NGX_OK;
2085     }
2086 
2087     v->len = r->request_body->temp_file->file.name.len;
2088     v->valid = 1;
2089     v->no_cacheable = 0;
2090     v->not_found = 0;
2091     v->data = r->request_body->temp_file->file.name.data;
2092 
2093     return NGX_OK;
2094 }
2095 
2096 
2097 static ngx_int_t
2098 ngx_http_variable_request_length(ngx_http_request_t *r,
2099     ngx_http_variable_value_t *v, uintptr_t data)
2100 {
2101     u_char  *p;
2102 
2103     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
2104     if (p == NULL) {
2105         return NGX_ERROR;
2106     }
2107 
2108     v->len = ngx_sprintf(p, "%O", r->request_length) - p;
2109     v->valid = 1;
2110     v->no_cacheable = 0;
2111     v->not_found = 0;
2112     v->data = p;
2113 
2114     return NGX_OK;
2115 }
2116 
2117 
2118 static ngx_int_t
2119 ngx_http_variable_request_time(ngx_http_request_t *r,
2120     ngx_http_variable_value_t *v, uintptr_t data)
2121 {
2122     u_char          *p;
2123     ngx_time_t      *tp;
2124     ngx_msec_int_t   ms;
2125 
2126     p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4);
2127     if (p == NULL) {
2128         return NGX_ERROR;
2129     }
2130 
2131     tp = ngx_timeofday();
2132 
2133     ms = (ngx_msec_int_t)
2134              ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec));
2135     ms = ngx_max(ms, 0);
2136 
2137     v->len = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000) - p;
2138     v->valid = 1;
2139     v->no_cacheable = 0;
2140     v->not_found = 0;
2141     v->data = p;
2142 
2143     return NGX_OK;
2144 }
2145 
2146 
2147 static ngx_int_t
2148 ngx_http_variable_request_id(ngx_http_request_t *r,
2149     ngx_http_variable_value_t *v, uintptr_t data)
2150 {
2151     u_char  *id;
2152 
2153 #if (NGX_OPENSSL)
2154     u_char   random_bytes[16];
2155 #endif
2156 
2157     id = ngx_pnalloc(r->pool, 32);
2158     if (id == NULL) {
2159         return NGX_ERROR;
2160     }
2161 
2162     v->valid = 1;
2163     v->no_cacheable = 0;
2164     v->not_found = 0;
2165 
2166     v->len = 32;
2167     v->data = id;
2168 
2169 #if (NGX_OPENSSL)
2170 
2171     if (RAND_bytes(random_bytes, 16) == 1) {
2172         ngx_hex_dump(id, random_bytes, 16);
2173         return NGX_OK;
2174     }
2175 
2176     ngx_ssl_error(NGX_LOG_ERR, r->connection->log, 0, "RAND_bytes() failed");
2177 
2178 #endif
2179 
2180     ngx_sprintf(id, "%08xD%08xD%08xD%08xD",
2181                 (uint32_t) ngx_random(), (uint32_t) ngx_random(),
2182                 (uint32_t) ngx_random(), (uint32_t) ngx_random());
2183 
2184     return NGX_OK;
2185 }
2186 
2187 
2188 static ngx_int_t
2189 ngx_http_variable_connection(ngx_http_request_t *r,
2190     ngx_http_variable_value_t *v, uintptr_t data)
2191 {
2192     u_char  *p;
2193 
2194     p = ngx_pnalloc(r->pool, NGX_ATOMIC_T_LEN);
2195     if (p == NULL) {
2196         return NGX_ERROR;
2197     }
2198 
2199     v->len = ngx_sprintf(p, "%uA", r->connection->number) - p;
2200     v->valid = 1;
2201     v->no_cacheable = 0;
2202     v->not_found = 0;
2203     v->data = p;
2204 
2205     return NGX_OK;
2206 }
2207 
2208 
2209 static ngx_int_t
2210 ngx_http_variable_connection_requests(ngx_http_request_t *r,
2211     ngx_http_variable_value_t *v, uintptr_t data)
2212 {
2213     u_char  *p;
2214 
2215     p = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
2216     if (p == NULL) {
2217         return NGX_ERROR;
2218     }
2219 
2220     v->len = ngx_sprintf(p, "%ui", r->connection->requests) - p;
2221     v->valid = 1;
2222     v->no_cacheable = 0;
2223     v->not_found = 0;
2224     v->data = p;
2225 
2226     return NGX_OK;
2227 }
2228 
2229 
2230 static ngx_int_t
2231 ngx_http_variable_nginx_version(ngx_http_request_t *r,
2232     ngx_http_variable_value_t *v, uintptr_t data)
2233 {
2234     v->len = sizeof(NGINX_VERSION) - 1;
2235     v->valid = 1;
2236     v->no_cacheable = 0;
2237     v->not_found = 0;
2238     v->data = (u_char *) NGINX_VERSION;
2239 
2240     return NGX_OK;
2241 }
2242 
2243 
2244 static ngx_int_t
2245 ngx_http_variable_hostname(ngx_http_request_t *r,
2246     ngx_http_variable_value_t *v, uintptr_t data)
2247 {
2248     v->len = ngx_cycle->hostname.len;
2249     v->valid = 1;
2250     v->no_cacheable = 0;
2251     v->not_found = 0;
2252     v->data = ngx_cycle->hostname.data;
2253 
2254     return NGX_OK;
2255 }
2256 
2257 
2258 static ngx_int_t
2259 ngx_http_variable_pid(ngx_http_request_t *r,
2260     ngx_http_variable_value_t *v, uintptr_t data)
2261 {
2262     u_char  *p;
2263 
2264     p = ngx_pnalloc(r->pool, NGX_INT64_LEN);
2265     if (p == NULL) {
2266         return NGX_ERROR;
2267     }
2268 
2269     v->len = ngx_sprintf(p, "%P", ngx_pid) - p;
2270     v->valid = 1;
2271     v->no_cacheable = 0;
2272     v->not_found = 0;
2273     v->data = p;
2274 
2275     return NGX_OK;
2276 }
2277 
2278 
2279 static ngx_int_t
2280 ngx_http_variable_msec(ngx_http_request_t *r,
2281     ngx_http_variable_value_t *v, uintptr_t data)
2282 {
2283     u_char      *p;
2284     ngx_time_t  *tp;
2285 
2286     p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4);
2287     if (p == NULL) {
2288         return NGX_ERROR;
2289     }
2290 
2291     tp = ngx_timeofday();
2292 
2293     v->len = ngx_sprintf(p, "%T.%03M", tp->sec, tp->msec) - p;
2294     v->valid = 1;
2295     v->no_cacheable = 0;
2296     v->not_found = 0;
2297     v->data = p;
2298 
2299     return NGX_OK;
2300 }
2301 
2302 
2303 static ngx_int_t
2304 ngx_http_variable_time_iso8601(ngx_http_request_t *r,
2305     ngx_http_variable_value_t *v, uintptr_t data)
2306 {
2307     u_char  *p;
2308 
2309     p = ngx_pnalloc(r->pool, ngx_cached_http_log_iso8601.len);
2310     if (p == NULL) {
2311         return NGX_ERROR;
2312     }
2313 
2314     ngx_memcpy(p, ngx_cached_http_log_iso8601.data,
2315                ngx_cached_http_log_iso8601.len);
2316 
2317     v->len = ngx_cached_http_log_iso8601.len;
2318     v->valid = 1;
2319     v->no_cacheable = 0;
2320     v->not_found = 0;
2321     v->data = p;
2322 
2323     return NGX_OK;
2324 }
2325 
2326 
2327 static ngx_int_t
2328 ngx_http_variable_time_local(ngx_http_request_t *r,
2329     ngx_http_variable_value_t *v, uintptr_t data)
2330 {
2331     u_char  *p;
2332 
2333     p = ngx_pnalloc(r->pool, ngx_cached_http_log_time.len);
2334     if (p == NULL) {
2335         return NGX_ERROR;
2336     }
2337 
2338     ngx_memcpy(p, ngx_cached_http_log_time.data, ngx_cached_http_log_time.len);
2339 
2340     v->len = ngx_cached_http_log_time.len;
2341     v->valid = 1;
2342     v->no_cacheable = 0;
2343     v->not_found = 0;
2344     v->data = p;
2345 
2346     return NGX_OK;
2347 }
2348 
2349 
2350 void *
2351 ngx_http_map_find(ngx_http_request_t *r, ngx_http_map_t *map, ngx_str_t *match)
2352 {
2353     void        *value;
2354     u_char      *low;
2355     size_t       len;
2356     ngx_uint_t   key;
2357 
2358     len = match->len;
2359 
2360     if (len) {
2361         low = ngx_pnalloc(r->pool, len);
2362         if (low == NULL) {
2363             return NULL;
2364         }
2365 
2366     } else {
2367         low = NULL;
2368     }
2369 
2370     key = ngx_hash_strlow(low, match->data, len);
2371 
2372     value = ngx_hash_find_combined(&map->hash, key, low, len);
2373     if (value) {
2374         return value;
2375     }
2376 
2377 #if (NGX_PCRE)
2378 
2379     if (len && map->nregex) {
2380         ngx_int_t              n;
2381         ngx_uint_t             i;
2382         ngx_http_map_regex_t  *reg;
2383 
2384         reg = map->regex;
2385 
2386         for (i = 0; i < map->nregex; i++) {
2387 
2388             n = ngx_http_regex_exec(r, reg[i].regex, match);
2389 
2390             if (n == NGX_OK) {
2391                 return reg[i].value;
2392             }
2393 
2394             if (n == NGX_DECLINED) {
2395                 continue;
2396             }
2397 
2398             /* NGX_ERROR */
2399 
2400             return NULL;
2401         }
2402     }
2403 
2404 #endif
2405 
2406     return NULL;
2407 }
2408 
2409 
2410 #if (NGX_PCRE)
2411 
2412 static ngx_int_t
2413 ngx_http_variable_not_found(ngx_http_request_t *r, ngx_http_variable_value_t *v,
2414     uintptr_t data)
2415 {
2416     v->not_found = 1;
2417     return NGX_OK;
2418 }
2419 
2420 
2421 ngx_http_regex_t *
2422 ngx_http_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc)
2423 {
2424     u_char                     *p;
2425     size_t                      size;
2426     ngx_str_t                   name;
2427     ngx_uint_t                  i, n;
2428     ngx_http_variable_t        *v;
2429     ngx_http_regex_t           *re;
2430     ngx_http_regex_variable_t  *rv;
2431     ngx_http_core_main_conf_t  *cmcf;
2432 
2433     rc->pool = cf->pool;
2434 
2435     if (ngx_regex_compile(rc) != NGX_OK) {
2436         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err);
2437         return NULL;
2438     }
2439 
2440     re = ngx_pcalloc(cf->pool, sizeof(ngx_http_regex_t));
2441     if (re == NULL) {
2442         return NULL;
2443     }
2444 
2445     re->regex = rc->regex;
2446     re->ncaptures = rc->captures;
2447     re->name = rc->pattern;
2448 
2449     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
2450     cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures);
2451 
2452     n = (ngx_uint_t) rc->named_captures;
2453 
2454     if (n == 0) {
2455         return re;
2456     }
2457 
2458     rv = ngx_palloc(rc->pool, n * sizeof(ngx_http_regex_variable_t));
2459     if (rv == NULL) {
2460         return NULL;
2461     }
2462 
2463     re->variables = rv;
2464     re->nvariables = n;
2465 
2466     size = rc->name_size;
2467     p = rc->names;
2468 
2469     for (i = 0; i < n; i++) {
2470         rv[i].capture = 2 * ((p[0] << 8) + p[1]);
2471 
2472         name.data = &p[2];
2473         name.len = ngx_strlen(name.data);
2474 
2475         v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
2476         if (v == NULL) {
2477             return NULL;
2478         }
2479 
2480         rv[i].index = ngx_http_get_variable_index(cf, &name);
2481         if (rv[i].index == NGX_ERROR) {
2482             return NULL;
2483         }
2484 
2485         v->get_handler = ngx_http_variable_not_found;
2486 
2487         p += size;
2488     }
2489 
2490     return re;
2491 }
2492 
2493 
2494 ngx_int_t
2495 ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, ngx_str_t *s)
2496 {
2497     ngx_int_t                   rc, index;
2498     ngx_uint_t                  i, n, len;
2499     ngx_http_variable_value_t  *vv;
2500     ngx_http_core_main_conf_t  *cmcf;
2501 
2502     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2503 
2504     if (re->ncaptures) {
2505         len = cmcf->ncaptures;
2506 
2507         if (r->captures == NULL) {
2508             r->captures = ngx_palloc(r->pool, len * sizeof(int));
2509             if (r->captures == NULL) {
2510                 return NGX_ERROR;
2511             }
2512         }
2513 
2514     } else {
2515         len = 0;
2516     }
2517 
2518     rc = ngx_regex_exec(re->regex, s, r->captures, len);
2519 
2520     if (rc == NGX_REGEX_NO_MATCHED) {
2521         return NGX_DECLINED;
2522     }
2523 
2524     if (rc < 0) {
2525         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
2526                       ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
2527                       rc, s, &re->name);
2528         return NGX_ERROR;
2529     }
2530 
2531     for (i = 0; i < re->nvariables; i++) {
2532 
2533         n = re->variables[i].capture;
2534         index = re->variables[i].index;
2535         vv = &r->variables[index];
2536 
2537         vv->len = r->captures[n + 1] - r->captures[n];
2538         vv->valid = 1;
2539         vv->no_cacheable = 0;
2540         vv->not_found = 0;
2541         vv->data = &s->data[r->captures[n]];
2542 
2543 #if (NGX_DEBUG)
2544         {
2545         ngx_http_variable_t  *v;
2546 
2547         v = cmcf->variables.elts;
2548 
2549         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2550                        "http regex set $%V to \"%v\"", &v[index].name, vv);
2551         }
2552 #endif
2553     }
2554 
2555     r->ncaptures = rc * 2;
2556     r->captures_data = s->data;
2557 
2558     return NGX_OK;
2559 }
2560 
2561 #endif
2562 
2563 
2564 ngx_int_t
2565 ngx_http_variables_add_core_vars(ngx_conf_t *cf)
2566 {
2567     ngx_http_variable_t        *cv, *v;
2568     ngx_http_core_main_conf_t  *cmcf;
2569 
2570     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
2571 
2572     cmcf->variables_keys = ngx_pcalloc(cf->temp_pool,
2573                                        sizeof(ngx_hash_keys_arrays_t));
2574     if (cmcf->variables_keys == NULL) {
2575         return NGX_ERROR;
2576     }
2577 
2578     cmcf->variables_keys->pool = cf->pool;
2579     cmcf->variables_keys->temp_pool = cf->pool;
2580 
2581     if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL)
2582         != NGX_OK)
2583     {
2584         return NGX_ERROR;
2585     }
2586 
2587     if (ngx_array_init(&cmcf->prefix_variables, cf->pool, 8,
2588                        sizeof(ngx_http_variable_t))
2589         != NGX_OK)
2590     {
2591         return NGX_ERROR;
2592     }
2593 
2594     for (cv = ngx_http_core_variables; cv->name.len; cv++) {
2595         v = ngx_http_add_variable(cf, &cv->name, cv->flags);
2596         if (v == NULL) {
2597             return NGX_ERROR;
2598         }
2599 
2600         *v = *cv;
2601     }
2602 
2603     return NGX_OK;
2604 }
2605 
2606 
2607 ngx_int_t
2608 ngx_http_variables_init_vars(ngx_conf_t *cf)
2609 {
2610     size_t                      len;
2611     ngx_uint_t                  i, n;
2612     ngx_hash_key_t             *key;
2613     ngx_hash_init_t             hash;
2614     ngx_http_variable_t        *v, *av, *pv;
2615     ngx_http_core_main_conf_t  *cmcf;
2616 
2617     /* set the handlers for the indexed http variables */
2618 
2619     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
2620 
2621     v = cmcf->variables.elts;
2622     pv = cmcf->prefix_variables.elts;
2623     key = cmcf->variables_keys->keys.elts;
2624 
2625     for (i = 0; i < cmcf->variables.nelts; i++) {
2626 
2627         for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {
2628 
2629             av = key[n].value;
2630 
2631             if (v[i].name.len == key[n].key.len
2632                 && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len)
2633                    == 0)
2634             {
2635                 v[i].get_handler = av->get_handler;
2636                 v[i].data = av->data;
2637 
2638                 av->flags |= NGX_HTTP_VAR_INDEXED;
2639                 v[i].flags = av->flags;
2640 
2641                 av->index = i;
2642 
2643                 if (av->get_handler == NULL
2644                     || (av->flags & NGX_HTTP_VAR_WEAK))
2645                 {
2646                     break;
2647                 }
2648 
2649                 goto next;
2650             }
2651         }
2652 
2653         len = 0;
2654         av = NULL;
2655 
2656         for (n = 0; n < cmcf->prefix_variables.nelts; n++) {
2657             if (v[i].name.len >= pv[n].name.len && v[i].name.len > len
2658                 && ngx_strncmp(v[i].name.data, pv[n].name.data, pv[n].name.len)
2659                    == 0)
2660             {
2661                 av = &pv[n];
2662                 len = pv[n].name.len;
2663             }
2664         }
2665 
2666         if (av) {
2667             v[i].get_handler = av->get_handler;
2668             v[i].data = (uintptr_t) &v[i].name;
2669             v[i].flags = av->flags;
2670 
2671             goto next;
2672         }
2673 
2674         if (v[i].get_handler == NULL) {
2675             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
2676                           "unknown \"%V\" variable", &v[i].name);
2677 
2678             return NGX_ERROR;
2679         }
2680 
2681     next:
2682         continue;
2683     }
2684 
2685 
2686     for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {
2687         av = key[n].value;
2688 
2689         if (av->flags & NGX_HTTP_VAR_NOHASH) {
2690             key[n].key.data = NULL;
2691         }
2692     }
2693 
2694 
2695     hash.hash = &cmcf->variables_hash;
2696     hash.key = ngx_hash_key;
2697     hash.max_size = cmcf->variables_hash_max_size;
2698     hash.bucket_size = cmcf->variables_hash_bucket_size;
2699     hash.name = "variables_hash";
2700     hash.pool = cf->pool;
2701     hash.temp_pool = NULL;
2702 
2703     if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts,
2704                       cmcf->variables_keys->keys.nelts)
2705         != NGX_OK)
2706     {
2707         return NGX_ERROR;
2708     }
2709 
2710     cmcf->variables_keys = NULL;
2711 
2712     return NGX_OK;
2713 }