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