Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.19.2 ]​[ nginx-1.18.0 ]​

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