Annotation of embedaddon/nginx/src/http/ngx_http_variables.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #include <ngx_config.h>
                      9: #include <ngx_core.h>
                     10: #include <ngx_http.h>
                     11: #include <nginx.h>
                     12: 
                     13: 
                     14: static ngx_int_t ngx_http_variable_request(ngx_http_request_t *r,
                     15:     ngx_http_variable_value_t *v, uintptr_t data);
                     16: static void ngx_http_variable_request_set(ngx_http_request_t *r,
                     17:     ngx_http_variable_value_t *v, uintptr_t data);
                     18: static ngx_int_t ngx_http_variable_request_get_size(ngx_http_request_t *r,
                     19:     ngx_http_variable_value_t *v, uintptr_t data);
                     20: static void ngx_http_variable_request_set_size(ngx_http_request_t *r,
                     21:     ngx_http_variable_value_t *v, uintptr_t data);
                     22: static ngx_int_t ngx_http_variable_header(ngx_http_request_t *r,
                     23:     ngx_http_variable_value_t *v, uintptr_t data);
                     24: 
                     25: static ngx_int_t ngx_http_variable_cookies(ngx_http_request_t *r,
                     26:     ngx_http_variable_value_t *v, uintptr_t data);
                     27: static ngx_int_t ngx_http_variable_headers(ngx_http_request_t *r,
                     28:     ngx_http_variable_value_t *v, uintptr_t data);
                     29: static ngx_int_t ngx_http_variable_headers_internal(ngx_http_request_t *r,
                     30:     ngx_http_variable_value_t *v, uintptr_t data, u_char sep);
                     31: 
                     32: static ngx_int_t ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
                     33:     ngx_http_variable_value_t *v, uintptr_t data);
                     34: static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
                     35:     ngx_http_variable_value_t *v, uintptr_t data);
                     36: static ngx_int_t ngx_http_variable_request_line(ngx_http_request_t *r,
                     37:     ngx_http_variable_value_t *v, uintptr_t data);
                     38: static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r,
                     39:     ngx_http_variable_value_t *v, uintptr_t data);
                     40: static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r,
                     41:     ngx_http_variable_value_t *v, uintptr_t data);
                     42: #if (NGX_HAVE_TCP_INFO)
                     43: static ngx_int_t ngx_http_variable_tcpinfo(ngx_http_request_t *r,
                     44:     ngx_http_variable_value_t *v, uintptr_t data);
                     45: #endif
                     46: 
                     47: static ngx_int_t ngx_http_variable_content_length(ngx_http_request_t *r,
                     48:     ngx_http_variable_value_t *v, uintptr_t data);
                     49: static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r,
                     50:     ngx_http_variable_value_t *v, uintptr_t data);
                     51: static ngx_int_t ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
                     52:     ngx_http_variable_value_t *v, uintptr_t data);
                     53: static ngx_int_t ngx_http_variable_remote_addr(ngx_http_request_t *r,
                     54:     ngx_http_variable_value_t *v, uintptr_t data);
                     55: static ngx_int_t ngx_http_variable_remote_port(ngx_http_request_t *r,
                     56:     ngx_http_variable_value_t *v, uintptr_t data);
                     57: static ngx_int_t ngx_http_variable_server_addr(ngx_http_request_t *r,
                     58:     ngx_http_variable_value_t *v, uintptr_t data);
                     59: static ngx_int_t ngx_http_variable_server_port(ngx_http_request_t *r,
                     60:     ngx_http_variable_value_t *v, uintptr_t data);
                     61: static ngx_int_t ngx_http_variable_scheme(ngx_http_request_t *r,
                     62:     ngx_http_variable_value_t *v, uintptr_t data);
                     63: static ngx_int_t ngx_http_variable_https(ngx_http_request_t *r,
                     64:     ngx_http_variable_value_t *v, uintptr_t data);
                     65: static ngx_int_t ngx_http_variable_is_args(ngx_http_request_t *r,
                     66:     ngx_http_variable_value_t *v, uintptr_t data);
                     67: static ngx_int_t ngx_http_variable_document_root(ngx_http_request_t *r,
                     68:     ngx_http_variable_value_t *v, uintptr_t data);
                     69: static ngx_int_t ngx_http_variable_realpath_root(ngx_http_request_t *r,
                     70:     ngx_http_variable_value_t *v, uintptr_t data);
                     71: static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r,
                     72:     ngx_http_variable_value_t *v, uintptr_t data);
                     73: static ngx_int_t ngx_http_variable_server_name(ngx_http_request_t *r,
                     74:     ngx_http_variable_value_t *v, uintptr_t data);
                     75: static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r,
                     76:     ngx_http_variable_value_t *v, uintptr_t data);
                     77: static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r,
                     78:     ngx_http_variable_value_t *v, uintptr_t data);
                     79: static ngx_int_t ngx_http_variable_bytes_sent(ngx_http_request_t *r,
                     80:     ngx_http_variable_value_t *v, uintptr_t data);
                     81: static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
                     82:     ngx_http_variable_value_t *v, uintptr_t data);
                     83: static ngx_int_t ngx_http_variable_pipe(ngx_http_request_t *r,
                     84:     ngx_http_variable_value_t *v, uintptr_t data);
                     85: static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
                     86:     ngx_http_variable_value_t *v, uintptr_t data);
                     87: static ngx_int_t ngx_http_variable_request_body(ngx_http_request_t *r,
                     88:     ngx_http_variable_value_t *v, uintptr_t data);
                     89: static ngx_int_t ngx_http_variable_request_body_file(ngx_http_request_t *r,
                     90:     ngx_http_variable_value_t *v, uintptr_t data);
                     91: static ngx_int_t ngx_http_variable_request_length(ngx_http_request_t *r,
                     92:     ngx_http_variable_value_t *v, uintptr_t data);
                     93: static ngx_int_t ngx_http_variable_request_time(ngx_http_request_t *r,
                     94:     ngx_http_variable_value_t *v, uintptr_t data);
                     95: static ngx_int_t ngx_http_variable_status(ngx_http_request_t *r,
                     96:     ngx_http_variable_value_t *v, uintptr_t data);
                     97: 
                     98: static ngx_int_t ngx_http_variable_sent_content_type(ngx_http_request_t *r,
                     99:     ngx_http_variable_value_t *v, uintptr_t data);
                    100: static ngx_int_t ngx_http_variable_sent_content_length(ngx_http_request_t *r,
                    101:     ngx_http_variable_value_t *v, uintptr_t data);
                    102: static ngx_int_t ngx_http_variable_sent_location(ngx_http_request_t *r,
                    103:     ngx_http_variable_value_t *v, uintptr_t data);
                    104: static ngx_int_t ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
                    105:     ngx_http_variable_value_t *v, uintptr_t data);
                    106: static ngx_int_t ngx_http_variable_sent_connection(ngx_http_request_t *r,
                    107:     ngx_http_variable_value_t *v, uintptr_t data);
                    108: static ngx_int_t ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
                    109:     ngx_http_variable_value_t *v, uintptr_t data);
                    110: static ngx_int_t ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
                    111:     ngx_http_variable_value_t *v, uintptr_t data);
                    112: 
                    113: static ngx_int_t ngx_http_variable_connection(ngx_http_request_t *r,
                    114:     ngx_http_variable_value_t *v, uintptr_t data);
                    115: static ngx_int_t ngx_http_variable_connection_requests(ngx_http_request_t *r,
                    116:     ngx_http_variable_value_t *v, uintptr_t data);
                    117: 
                    118: static ngx_int_t ngx_http_variable_nginx_version(ngx_http_request_t *r,
                    119:     ngx_http_variable_value_t *v, uintptr_t data);
                    120: static ngx_int_t ngx_http_variable_hostname(ngx_http_request_t *r,
                    121:     ngx_http_variable_value_t *v, uintptr_t data);
                    122: static ngx_int_t ngx_http_variable_pid(ngx_http_request_t *r,
                    123:     ngx_http_variable_value_t *v, uintptr_t data);
                    124: static ngx_int_t ngx_http_variable_msec(ngx_http_request_t *r,
                    125:     ngx_http_variable_value_t *v, uintptr_t data);
                    126: static ngx_int_t ngx_http_variable_time_iso8601(ngx_http_request_t *r,
                    127:     ngx_http_variable_value_t *v, uintptr_t data);
                    128: static ngx_int_t ngx_http_variable_time_local(ngx_http_request_t *r,
                    129:     ngx_http_variable_value_t *v, uintptr_t data);
                    130: 
                    131: /*
                    132:  * TODO:
                    133:  *     Apache CGI: AUTH_TYPE, PATH_INFO (null), PATH_TRANSLATED
                    134:  *                 REMOTE_HOST (null), REMOTE_IDENT (null),
                    135:  *                 SERVER_SOFTWARE
                    136:  *
                    137:  *     Apache SSI: DOCUMENT_NAME, LAST_MODIFIED, USER_NAME (file owner)
                    138:  */
                    139: 
                    140: /*
                    141:  * the $http_host, $http_user_agent, $http_referer, and $http_via
                    142:  * variables may be handled by generic
                    143:  * ngx_http_variable_unknown_header_in(), but for performance reasons
                    144:  * they are handled using dedicated entries
                    145:  */
                    146: 
                    147: static ngx_http_variable_t  ngx_http_core_variables[] = {
                    148: 
                    149:     { ngx_string("http_host"), NULL, ngx_http_variable_header,
                    150:       offsetof(ngx_http_request_t, headers_in.host), 0, 0 },
                    151: 
                    152:     { ngx_string("http_user_agent"), NULL, ngx_http_variable_header,
                    153:       offsetof(ngx_http_request_t, headers_in.user_agent), 0, 0 },
                    154: 
                    155:     { ngx_string("http_referer"), NULL, ngx_http_variable_header,
                    156:       offsetof(ngx_http_request_t, headers_in.referer), 0, 0 },
                    157: 
                    158: #if (NGX_HTTP_GZIP)
                    159:     { ngx_string("http_via"), NULL, ngx_http_variable_header,
                    160:       offsetof(ngx_http_request_t, headers_in.via), 0, 0 },
                    161: #endif
                    162: 
                    163: #if (NGX_HTTP_X_FORWARDED_FOR)
                    164:     { ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_headers,
                    165:       offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 },
                    166: #endif
                    167: 
                    168:     { ngx_string("http_cookie"), NULL, ngx_http_variable_cookies,
                    169:       offsetof(ngx_http_request_t, headers_in.cookies), 0, 0 },
                    170: 
                    171:     { ngx_string("content_length"), NULL, ngx_http_variable_content_length,
                    172:       0, 0, 0 },
                    173: 
                    174:     { ngx_string("content_type"), NULL, ngx_http_variable_header,
                    175:       offsetof(ngx_http_request_t, headers_in.content_type), 0, 0 },
                    176: 
                    177:     { ngx_string("host"), NULL, ngx_http_variable_host, 0, 0, 0 },
                    178: 
                    179:     { ngx_string("binary_remote_addr"), NULL,
                    180:       ngx_http_variable_binary_remote_addr, 0, 0, 0 },
                    181: 
                    182:     { ngx_string("remote_addr"), NULL, ngx_http_variable_remote_addr, 0, 0, 0 },
                    183: 
                    184:     { ngx_string("remote_port"), NULL, ngx_http_variable_remote_port, 0, 0, 0 },
                    185: 
                    186:     { ngx_string("server_addr"), NULL, ngx_http_variable_server_addr, 0, 0, 0 },
                    187: 
                    188:     { ngx_string("server_port"), NULL, ngx_http_variable_server_port, 0, 0, 0 },
                    189: 
                    190:     { ngx_string("server_protocol"), NULL, ngx_http_variable_request,
                    191:       offsetof(ngx_http_request_t, http_protocol), 0, 0 },
                    192: 
                    193:     { ngx_string("scheme"), NULL, ngx_http_variable_scheme, 0, 0, 0 },
                    194: 
                    195:     { ngx_string("https"), NULL, ngx_http_variable_https, 0, 0, 0 },
                    196: 
                    197:     { ngx_string("request_uri"), NULL, ngx_http_variable_request,
                    198:       offsetof(ngx_http_request_t, unparsed_uri), 0, 0 },
                    199: 
                    200:     { ngx_string("uri"), NULL, ngx_http_variable_request,
                    201:       offsetof(ngx_http_request_t, uri),
                    202:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    203: 
                    204:     { ngx_string("document_uri"), NULL, ngx_http_variable_request,
                    205:       offsetof(ngx_http_request_t, uri),
                    206:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    207: 
                    208:     { ngx_string("request"), NULL, ngx_http_variable_request_line, 0, 0, 0 },
                    209: 
                    210:     { ngx_string("document_root"), NULL,
                    211:       ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    212: 
                    213:     { ngx_string("realpath_root"), NULL,
                    214:       ngx_http_variable_realpath_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    215: 
                    216:     { ngx_string("query_string"), NULL, ngx_http_variable_request,
                    217:       offsetof(ngx_http_request_t, args),
                    218:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    219: 
                    220:     { ngx_string("args"),
                    221:       ngx_http_variable_request_set,
                    222:       ngx_http_variable_request,
                    223:       offsetof(ngx_http_request_t, args),
                    224:       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    225: 
                    226:     { ngx_string("is_args"), NULL, ngx_http_variable_is_args,
                    227:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    228: 
                    229:     { ngx_string("request_filename"), NULL,
                    230:       ngx_http_variable_request_filename, 0,
                    231:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    232: 
                    233:     { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 },
                    234: 
                    235:     { ngx_string("request_method"), NULL,
                    236:       ngx_http_variable_request_method, 0,
                    237:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    238: 
                    239:     { ngx_string("remote_user"), NULL, ngx_http_variable_remote_user, 0, 0, 0 },
                    240: 
                    241:     { ngx_string("bytes_sent"), NULL, ngx_http_variable_bytes_sent,
                    242:       0, 0, 0 },
                    243: 
                    244:     { ngx_string("body_bytes_sent"), NULL, ngx_http_variable_body_bytes_sent,
                    245:       0, 0, 0 },
                    246: 
                    247:     { ngx_string("pipe"), NULL, ngx_http_variable_pipe,
                    248:       0, 0, 0 },
                    249: 
                    250:     { ngx_string("request_completion"), NULL,
                    251:       ngx_http_variable_request_completion,
                    252:       0, 0, 0 },
                    253: 
                    254:     { ngx_string("request_body"), NULL,
                    255:       ngx_http_variable_request_body,
                    256:       0, 0, 0 },
                    257: 
                    258:     { ngx_string("request_body_file"), NULL,
                    259:       ngx_http_variable_request_body_file,
                    260:       0, 0, 0 },
                    261: 
                    262:     { ngx_string("request_length"), NULL, ngx_http_variable_request_length,
                    263:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    264: 
                    265:     { ngx_string("request_time"), NULL, ngx_http_variable_request_time,
                    266:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    267: 
                    268:     { ngx_string("status"), NULL,
                    269:       ngx_http_variable_status, 0,
                    270:       NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    271: 
                    272:     { ngx_string("sent_http_content_type"), NULL,
                    273:       ngx_http_variable_sent_content_type, 0, 0, 0 },
                    274: 
                    275:     { ngx_string("sent_http_content_length"), NULL,
                    276:       ngx_http_variable_sent_content_length, 0, 0, 0 },
                    277: 
                    278:     { ngx_string("sent_http_location"), NULL,
                    279:       ngx_http_variable_sent_location, 0, 0, 0 },
                    280: 
                    281:     { ngx_string("sent_http_last_modified"), NULL,
                    282:       ngx_http_variable_sent_last_modified, 0, 0, 0 },
                    283: 
                    284:     { ngx_string("sent_http_connection"), NULL,
                    285:       ngx_http_variable_sent_connection, 0, 0, 0 },
                    286: 
                    287:     { ngx_string("sent_http_keep_alive"), NULL,
                    288:       ngx_http_variable_sent_keep_alive, 0, 0, 0 },
                    289: 
                    290:     { ngx_string("sent_http_transfer_encoding"), NULL,
                    291:       ngx_http_variable_sent_transfer_encoding, 0, 0, 0 },
                    292: 
                    293:     { ngx_string("sent_http_cache_control"), NULL, ngx_http_variable_headers,
                    294:       offsetof(ngx_http_request_t, headers_out.cache_control), 0, 0 },
                    295: 
                    296:     { ngx_string("limit_rate"), ngx_http_variable_request_set_size,
                    297:       ngx_http_variable_request_get_size,
                    298:       offsetof(ngx_http_request_t, limit_rate),
                    299:       NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    300: 
                    301:     { ngx_string("connection"), NULL,
                    302:       ngx_http_variable_connection, 0, 0, 0 },
                    303: 
                    304:     { ngx_string("connection_requests"), NULL,
                    305:       ngx_http_variable_connection_requests, 0, 0, 0 },
                    306: 
                    307:     { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version,
                    308:       0, 0, 0 },
                    309: 
                    310:     { ngx_string("hostname"), NULL, ngx_http_variable_hostname,
                    311:       0, 0, 0 },
                    312: 
                    313:     { ngx_string("pid"), NULL, ngx_http_variable_pid,
                    314:       0, 0, 0 },
                    315: 
                    316:     { ngx_string("msec"), NULL, ngx_http_variable_msec,
                    317:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    318: 
                    319:     { ngx_string("time_iso8601"), NULL, ngx_http_variable_time_iso8601,
                    320:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    321: 
                    322:     { ngx_string("time_local"), NULL, ngx_http_variable_time_local,
                    323:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    324: 
                    325: #if (NGX_HAVE_TCP_INFO)
                    326:     { ngx_string("tcpinfo_rtt"), NULL, ngx_http_variable_tcpinfo,
                    327:       0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    328: 
                    329:     { ngx_string("tcpinfo_rttvar"), NULL, ngx_http_variable_tcpinfo,
                    330:       1, NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    331: 
                    332:     { ngx_string("tcpinfo_snd_cwnd"), NULL, ngx_http_variable_tcpinfo,
                    333:       2, NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    334: 
                    335:     { ngx_string("tcpinfo_rcv_space"), NULL, ngx_http_variable_tcpinfo,
                    336:       3, NGX_HTTP_VAR_NOCACHEABLE, 0 },
                    337: #endif
                    338: 
                    339:     { ngx_null_string, NULL, NULL, 0, 0, 0 }
                    340: };
                    341: 
                    342: 
                    343: ngx_http_variable_value_t  ngx_http_variable_null_value =
                    344:     ngx_http_variable("");
                    345: ngx_http_variable_value_t  ngx_http_variable_true_value =
                    346:     ngx_http_variable("1");
                    347: 
                    348: 
                    349: ngx_http_variable_t *
                    350: ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
                    351: {
                    352:     ngx_int_t                   rc;
                    353:     ngx_uint_t                  i;
                    354:     ngx_hash_key_t             *key;
                    355:     ngx_http_variable_t        *v;
                    356:     ngx_http_core_main_conf_t  *cmcf;
                    357: 
                    358:     if (name->len == 0) {
                    359:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                    360:                            "invalid variable name \"$\"");
                    361:         return NULL;
                    362:     }
                    363: 
                    364:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
                    365: 
                    366:     key = cmcf->variables_keys->keys.elts;
                    367:     for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) {
                    368:         if (name->len != key[i].key.len
                    369:             || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0)
                    370:         {
                    371:             continue;
                    372:         }
                    373: 
                    374:         v = key[i].value;
                    375: 
                    376:         if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
                    377:             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                    378:                                "the duplicate \"%V\" variable", name);
                    379:             return NULL;
                    380:         }
                    381: 
                    382:         return v;
                    383:     }
                    384: 
                    385:     v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));
                    386:     if (v == NULL) {
                    387:         return NULL;
                    388:     }
                    389: 
                    390:     v->name.len = name->len;
                    391:     v->name.data = ngx_pnalloc(cf->pool, name->len);
                    392:     if (v->name.data == NULL) {
                    393:         return NULL;
                    394:     }
                    395: 
                    396:     ngx_strlow(v->name.data, name->data, name->len);
                    397: 
                    398:     v->set_handler = NULL;
                    399:     v->get_handler = NULL;
                    400:     v->data = 0;
                    401:     v->flags = flags;
                    402:     v->index = 0;
                    403: 
                    404:     rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0);
                    405: 
                    406:     if (rc == NGX_ERROR) {
                    407:         return NULL;
                    408:     }
                    409: 
                    410:     if (rc == NGX_BUSY) {
                    411:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                    412:                            "conflicting variable name \"%V\"", name);
                    413:         return NULL;
                    414:     }
                    415: 
                    416:     return v;
                    417: }
                    418: 
                    419: 
                    420: ngx_int_t
                    421: ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name)
                    422: {
                    423:     ngx_uint_t                  i;
                    424:     ngx_http_variable_t        *v;
                    425:     ngx_http_core_main_conf_t  *cmcf;
                    426: 
                    427:     if (name->len == 0) {
                    428:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                    429:                            "invalid variable name \"$\"");
                    430:         return NGX_ERROR;
                    431:     }
                    432: 
                    433:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
                    434: 
                    435:     v = cmcf->variables.elts;
                    436: 
                    437:     if (v == NULL) {
                    438:         if (ngx_array_init(&cmcf->variables, cf->pool, 4,
                    439:                            sizeof(ngx_http_variable_t))
                    440:             != NGX_OK)
                    441:         {
                    442:             return NGX_ERROR;
                    443:         }
                    444: 
                    445:     } else {
                    446:         for (i = 0; i < cmcf->variables.nelts; i++) {
                    447:             if (name->len != v[i].name.len
                    448:                 || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0)
                    449:             {
                    450:                 continue;
                    451:             }
                    452: 
                    453:             return i;
                    454:         }
                    455:     }
                    456: 
                    457:     v = ngx_array_push(&cmcf->variables);
                    458:     if (v == NULL) {
                    459:         return NGX_ERROR;
                    460:     }
                    461: 
                    462:     v->name.len = name->len;
                    463:     v->name.data = ngx_pnalloc(cf->pool, name->len);
                    464:     if (v->name.data == NULL) {
                    465:         return NGX_ERROR;
                    466:     }
                    467: 
                    468:     ngx_strlow(v->name.data, name->data, name->len);
                    469: 
                    470:     v->set_handler = NULL;
                    471:     v->get_handler = NULL;
                    472:     v->data = 0;
                    473:     v->flags = 0;
                    474:     v->index = cmcf->variables.nelts - 1;
                    475: 
                    476:     return v->index;
                    477: }
                    478: 
                    479: 
                    480: ngx_http_variable_value_t *
                    481: ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
                    482: {
                    483:     ngx_http_variable_t        *v;
                    484:     ngx_http_core_main_conf_t  *cmcf;
                    485: 
                    486:     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
                    487: 
                    488:     if (cmcf->variables.nelts <= index) {
                    489:         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                    490:                       "unknown variable index: %d", index);
                    491:         return NULL;
                    492:     }
                    493: 
                    494:     if (r->variables[index].not_found || r->variables[index].valid) {
                    495:         return &r->variables[index];
                    496:     }
                    497: 
                    498:     v = cmcf->variables.elts;
                    499: 
                    500:     if (v[index].get_handler(r, &r->variables[index], v[index].data)
                    501:         == NGX_OK)
                    502:     {
                    503:         if (v[index].flags & NGX_HTTP_VAR_NOCACHEABLE) {
                    504:             r->variables[index].no_cacheable = 1;
                    505:         }
                    506: 
                    507:         return &r->variables[index];
                    508:     }
                    509: 
                    510:     r->variables[index].valid = 0;
                    511:     r->variables[index].not_found = 1;
                    512: 
                    513:     return NULL;
                    514: }
                    515: 
                    516: 
                    517: ngx_http_variable_value_t *
                    518: ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index)
                    519: {
                    520:     ngx_http_variable_value_t  *v;
                    521: 
                    522:     v = &r->variables[index];
                    523: 
                    524:     if (v->valid || v->not_found) {
                    525:         if (!v->no_cacheable) {
                    526:             return v;
                    527:         }
                    528: 
                    529:         v->valid = 0;
                    530:         v->not_found = 0;
                    531:     }
                    532: 
                    533:     return ngx_http_get_indexed_variable(r, index);
                    534: }
                    535: 
                    536: 
                    537: ngx_http_variable_value_t *
                    538: ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
                    539: {
                    540:     ngx_http_variable_t        *v;
                    541:     ngx_http_variable_value_t  *vv;
                    542:     ngx_http_core_main_conf_t  *cmcf;
                    543: 
                    544:     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
                    545: 
                    546:     v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len);
                    547: 
                    548:     if (v) {
                    549:         if (v->flags & NGX_HTTP_VAR_INDEXED) {
                    550:             return ngx_http_get_flushed_variable(r, v->index);
                    551: 
                    552:         } else {
                    553: 
                    554:             vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
                    555: 
                    556:             if (vv && v->get_handler(r, vv, v->data) == NGX_OK) {
                    557:                 return vv;
                    558:             }
                    559: 
                    560:             return NULL;
                    561:         }
                    562:     }
                    563: 
                    564:     vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
                    565:     if (vv == NULL) {
                    566:         return NULL;
                    567:     }
                    568: 
                    569:     if (ngx_strncmp(name->data, "http_", 5) == 0) {
                    570: 
                    571:         if (ngx_http_variable_unknown_header_in(r, vv, (uintptr_t) name)
                    572:             == NGX_OK)
                    573:         {
                    574:             return vv;
                    575:         }
                    576: 
                    577:         return NULL;
                    578:     }
                    579: 
                    580:     if (ngx_strncmp(name->data, "sent_http_", 10) == 0) {
                    581: 
                    582:         if (ngx_http_variable_unknown_header_out(r, vv, (uintptr_t) name)
                    583:             == NGX_OK)
                    584:         {
                    585:             return vv;
                    586:         }
                    587: 
                    588:         return NULL;
                    589:     }
                    590: 
                    591:     if (ngx_strncmp(name->data, "upstream_http_", 14) == 0) {
                    592: 
                    593:         if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name)
                    594:             == NGX_OK)
                    595:         {
                    596:             return vv;
                    597:         }
                    598: 
                    599:         return NULL;
                    600:     }
                    601: 
                    602:     if (ngx_strncmp(name->data, "cookie_", 7) == 0) {
                    603: 
                    604:         if (ngx_http_variable_cookie(r, vv, (uintptr_t) name) == NGX_OK) {
                    605:             return vv;
                    606:         }
                    607: 
                    608:         return NULL;
                    609:     }
                    610: 
                    611:     if (ngx_strncmp(name->data, "arg_", 4) == 0) {
                    612: 
                    613:         if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) {
                    614:             return vv;
                    615:         }
                    616: 
                    617:         return NULL;
                    618:     }
                    619: 
                    620:     vv->not_found = 1;
                    621: 
                    622:     return vv;
                    623: }
                    624: 
                    625: 
                    626: static ngx_int_t
                    627: ngx_http_variable_request(ngx_http_request_t *r, ngx_http_variable_value_t *v,
                    628:     uintptr_t data)
                    629: {
                    630:     ngx_str_t  *s;
                    631: 
                    632:     s = (ngx_str_t *) ((char *) r + data);
                    633: 
                    634:     if (s->data) {
                    635:         v->len = s->len;
                    636:         v->valid = 1;
                    637:         v->no_cacheable = 0;
                    638:         v->not_found = 0;
                    639:         v->data = s->data;
                    640: 
                    641:     } else {
                    642:         v->not_found = 1;
                    643:     }
                    644: 
                    645:     return NGX_OK;
                    646: }
                    647: 
                    648: 
                    649: static void
                    650: ngx_http_variable_request_set(ngx_http_request_t *r,
                    651:     ngx_http_variable_value_t *v, uintptr_t data)
                    652: {
                    653:     ngx_str_t  *s;
                    654: 
                    655:     s = (ngx_str_t *) ((char *) r + data);
                    656: 
                    657:     s->len = v->len;
                    658:     s->data = v->data;
                    659: }
                    660: 
                    661: 
                    662: static ngx_int_t
                    663: ngx_http_variable_request_get_size(ngx_http_request_t *r,
                    664:     ngx_http_variable_value_t *v, uintptr_t data)
                    665: {
                    666:     size_t  *sp;
                    667: 
                    668:     sp = (size_t *) ((char *) r + data);
                    669: 
                    670:     v->data = ngx_pnalloc(r->pool, NGX_SIZE_T_LEN);
                    671:     if (v->data == NULL) {
                    672:         return NGX_ERROR;
                    673:     }
                    674: 
                    675:     v->len = ngx_sprintf(v->data, "%uz", *sp) - v->data;
                    676:     v->valid = 1;
                    677:     v->no_cacheable = 0;
                    678:     v->not_found = 0;
                    679: 
                    680:     return NGX_OK;
                    681: }
                    682: 
                    683: 
                    684: static void
                    685: ngx_http_variable_request_set_size(ngx_http_request_t *r,
                    686:     ngx_http_variable_value_t *v, uintptr_t data)
                    687: {
                    688:     ssize_t    s, *sp;
                    689:     ngx_str_t  val;
                    690: 
                    691:     val.len = v->len;
                    692:     val.data = v->data;
                    693: 
                    694:     s = ngx_parse_size(&val);
                    695: 
                    696:     if (s == NGX_ERROR) {
                    697:         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                    698:                       "invalid size \"%V\"", &val);
                    699:         return;
                    700:     }
                    701: 
                    702:     sp = (ssize_t *) ((char *) r + data);
                    703: 
                    704:     *sp = s;
                    705: 
                    706:     return;
                    707: }
                    708: 
                    709: 
                    710: static ngx_int_t
                    711: ngx_http_variable_header(ngx_http_request_t *r, ngx_http_variable_value_t *v,
                    712:     uintptr_t data)
                    713: {
                    714:     ngx_table_elt_t  *h;
                    715: 
                    716:     h = *(ngx_table_elt_t **) ((char *) r + data);
                    717: 
                    718:     if (h) {
                    719:         v->len = h->value.len;
                    720:         v->valid = 1;
                    721:         v->no_cacheable = 0;
                    722:         v->not_found = 0;
                    723:         v->data = h->value.data;
                    724: 
                    725:     } else {
                    726:         v->not_found = 1;
                    727:     }
                    728: 
                    729:     return NGX_OK;
                    730: }
                    731: 
                    732: 
                    733: static ngx_int_t
                    734: ngx_http_variable_cookies(ngx_http_request_t *r,
                    735:     ngx_http_variable_value_t *v, uintptr_t data)
                    736: {
                    737:     return ngx_http_variable_headers_internal(r, v, data, ';');
                    738: }
                    739: 
                    740: 
                    741: static ngx_int_t
                    742: ngx_http_variable_headers(ngx_http_request_t *r,
                    743:     ngx_http_variable_value_t *v, uintptr_t data)
                    744: {
                    745:     return ngx_http_variable_headers_internal(r, v, data, ',');
                    746: }
                    747: 
                    748: 
                    749: static ngx_int_t
                    750: ngx_http_variable_headers_internal(ngx_http_request_t *r,
                    751:     ngx_http_variable_value_t *v, uintptr_t data, u_char sep)
                    752: {
                    753:     size_t             len;
                    754:     u_char            *p, *end;
                    755:     ngx_uint_t         i, n;
                    756:     ngx_array_t       *a;
                    757:     ngx_table_elt_t  **h;
                    758: 
                    759:     a = (ngx_array_t *) ((char *) r + data);
                    760: 
                    761:     n = a->nelts;
                    762:     h = a->elts;
                    763: 
                    764:     len = 0;
                    765: 
                    766:     for (i = 0; i < n; i++) {
                    767: 
                    768:         if (h[i]->hash == 0) {
                    769:             continue;
                    770:         }
                    771: 
                    772:         len += h[i]->value.len + 2;
                    773:     }
                    774: 
                    775:     if (len == 0) {
                    776:         v->not_found = 1;
                    777:         return NGX_OK;
                    778:     }
                    779: 
                    780:     len -= 2;
                    781: 
                    782:     v->valid = 1;
                    783:     v->no_cacheable = 0;
                    784:     v->not_found = 0;
                    785: 
                    786:     if (n == 1) {
                    787:         v->len = (*h)->value.len;
                    788:         v->data = (*h)->value.data;
                    789: 
                    790:         return NGX_OK;
                    791:     }
                    792: 
                    793:     p = ngx_pnalloc(r->pool, len);
                    794:     if (p == NULL) {
                    795:         return NGX_ERROR;
                    796:     }
                    797: 
                    798:     v->len = len;
                    799:     v->data = p;
                    800: 
                    801:     end = p + len;
                    802: 
                    803:     for (i = 0; /* void */ ; i++) {
                    804: 
                    805:         if (h[i]->hash == 0) {
                    806:             continue;
                    807:         }
                    808: 
                    809:         p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
                    810: 
                    811:         if (p == end) {
                    812:             break;
                    813:         }
                    814: 
                    815:         *p++ = sep; *p++ = ' ';
                    816:     }
                    817: 
                    818:     return NGX_OK;
                    819: }
                    820: 
                    821: 
                    822: static ngx_int_t
                    823: ngx_http_variable_unknown_header_in(ngx_http_request_t *r,
                    824:     ngx_http_variable_value_t *v, uintptr_t data)
                    825: {
                    826:     return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
                    827:                                             &r->headers_in.headers.part,
                    828:                                             sizeof("http_") - 1);
                    829: }
                    830: 
                    831: 
                    832: static ngx_int_t
                    833: ngx_http_variable_unknown_header_out(ngx_http_request_t *r,
                    834:     ngx_http_variable_value_t *v, uintptr_t data)
                    835: {
                    836:     return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
                    837:                                             &r->headers_out.headers.part,
                    838:                                             sizeof("sent_http_") - 1);
                    839: }
                    840: 
                    841: 
                    842: ngx_int_t
                    843: ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var,
                    844:     ngx_list_part_t *part, size_t prefix)
                    845: {
                    846:     u_char            ch;
                    847:     ngx_uint_t        i, n;
                    848:     ngx_table_elt_t  *header;
                    849: 
                    850:     header = part->elts;
                    851: 
                    852:     for (i = 0; /* void */ ; i++) {
                    853: 
                    854:         if (i >= part->nelts) {
                    855:             if (part->next == NULL) {
                    856:                 break;
                    857:             }
                    858: 
                    859:             part = part->next;
                    860:             header = part->elts;
                    861:             i = 0;
                    862:         }
                    863: 
                    864:         if (header[i].hash == 0) {
                    865:             continue;
                    866:         }
                    867: 
                    868:         for (n = 0; n + prefix < var->len && n < header[i].key.len; n++) {
                    869:             ch = header[i].key.data[n];
                    870: 
                    871:             if (ch >= 'A' && ch <= 'Z') {
                    872:                 ch |= 0x20;
                    873: 
                    874:             } else if (ch == '-') {
                    875:                 ch = '_';
                    876:             }
                    877: 
                    878:             if (var->data[n + prefix] != ch) {
                    879:                 break;
                    880:             }
                    881:         }
                    882: 
                    883:         if (n + prefix == var->len && n == header[i].key.len) {
                    884:             v->len = header[i].value.len;
                    885:             v->valid = 1;
                    886:             v->no_cacheable = 0;
                    887:             v->not_found = 0;
                    888:             v->data = header[i].value.data;
                    889: 
                    890:             return NGX_OK;
                    891:         }
                    892:     }
                    893: 
                    894:     v->not_found = 1;
                    895: 
                    896:     return NGX_OK;
                    897: }
                    898: 
                    899: 
                    900: static ngx_int_t
                    901: ngx_http_variable_request_line(ngx_http_request_t *r,
                    902:     ngx_http_variable_value_t *v, uintptr_t data)
                    903: {
                    904:     u_char  *p, *s;
                    905: 
                    906:     s = r->request_line.data;
                    907: 
                    908:     if (s == NULL) {
                    909:         s = r->request_start;
                    910: 
                    911:         if (s == NULL) {
                    912:             v->not_found = 1;
                    913:             return NGX_OK;
                    914:         }
                    915: 
                    916:         for (p = s; p < r->header_in->last; p++) {
                    917:             if (*p == CR || *p == LF) {
                    918:                 break;
                    919:             }
                    920:         }
                    921: 
                    922:         r->request_line.len = p - s;
                    923:         r->request_line.data = s;
                    924:     }
                    925: 
                    926:     v->len = r->request_line.len;
                    927:     v->valid = 1;
                    928:     v->no_cacheable = 0;
                    929:     v->not_found = 0;
                    930:     v->data = s;
                    931: 
                    932:     return NGX_OK;
                    933: }
                    934: 
                    935: 
                    936: static ngx_int_t
                    937: ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v,
                    938:     uintptr_t data)
                    939: {
                    940:     ngx_str_t *name = (ngx_str_t *) data;
                    941: 
                    942:     ngx_str_t  cookie, s;
                    943: 
                    944:     s.len = name->len - (sizeof("cookie_") - 1);
                    945:     s.data = name->data + sizeof("cookie_") - 1;
                    946: 
                    947:     if (ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &s, &cookie)
                    948:         == NGX_DECLINED)
                    949:     {
                    950:         v->not_found = 1;
                    951:         return NGX_OK;
                    952:     }
                    953: 
                    954:     v->len = cookie.len;
                    955:     v->valid = 1;
                    956:     v->no_cacheable = 0;
                    957:     v->not_found = 0;
                    958:     v->data = cookie.data;
                    959: 
                    960:     return NGX_OK;
                    961: }
                    962: 
                    963: 
                    964: static ngx_int_t
                    965: ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v,
                    966:     uintptr_t data)
                    967: {
                    968:     ngx_str_t *name = (ngx_str_t *) data;
                    969: 
                    970:     u_char     *arg;
                    971:     size_t      len;
                    972:     ngx_str_t   value;
                    973: 
                    974:     len = name->len - (sizeof("arg_") - 1);
                    975:     arg = name->data + sizeof("arg_") - 1;
                    976: 
                    977:     if (ngx_http_arg(r, arg, len, &value) != NGX_OK) {
                    978:         v->not_found = 1;
                    979:         return NGX_OK;
                    980:     }
                    981: 
                    982:     v->data = value.data;
                    983:     v->len = value.len;
                    984:     v->valid = 1;
                    985:     v->no_cacheable = 0;
                    986:     v->not_found = 0;
                    987: 
                    988:     return NGX_OK;
                    989: }
                    990: 
                    991: 
                    992: #if (NGX_HAVE_TCP_INFO)
                    993: 
                    994: static ngx_int_t
                    995: ngx_http_variable_tcpinfo(ngx_http_request_t *r, ngx_http_variable_value_t *v,
                    996:     uintptr_t data)
                    997: {
                    998:     struct tcp_info  ti;
                    999:     socklen_t        len;
                   1000:     uint32_t         value;
                   1001: 
                   1002:     len = sizeof(struct tcp_info);
                   1003:     if (getsockopt(r->connection->fd, IPPROTO_TCP, TCP_INFO, &ti, &len) == -1) {
                   1004:         v->not_found = 1;
                   1005:         return NGX_OK;
                   1006:     }
                   1007: 
                   1008:     v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN);
                   1009:     if (v->data == NULL) {
                   1010:         return NGX_ERROR;
                   1011:     }
                   1012: 
                   1013:     switch (data) {
                   1014:     case 0:
                   1015:         value = ti.tcpi_rtt;
                   1016:         break;
                   1017: 
                   1018:     case 1:
                   1019:         value = ti.tcpi_rttvar;
                   1020:         break;
                   1021: 
                   1022:     case 2:
                   1023:         value = ti.tcpi_snd_cwnd;
                   1024:         break;
                   1025: 
                   1026:     case 3:
                   1027:         value = ti.tcpi_rcv_space;
                   1028:         break;
                   1029: 
                   1030:     /* suppress warning */
                   1031:     default:
                   1032:         value = 0;
                   1033:         break;
                   1034:     }
                   1035: 
                   1036:     v->len = ngx_sprintf(v->data, "%uD", value) - v->data;
                   1037:     v->valid = 1;
                   1038:     v->no_cacheable = 0;
                   1039:     v->not_found = 0;
                   1040: 
                   1041:     return NGX_OK;
                   1042: }
                   1043: 
                   1044: #endif
                   1045: 
                   1046: 
                   1047: static ngx_int_t
                   1048: ngx_http_variable_content_length(ngx_http_request_t *r,
                   1049:     ngx_http_variable_value_t *v, uintptr_t data)
                   1050: {
                   1051:     u_char  *p;
                   1052: 
                   1053:     if (r->headers_in.content_length) {
                   1054:         v->len = r->headers_in.content_length->value.len;
                   1055:         v->data = r->headers_in.content_length->value.data;
                   1056:         v->valid = 1;
                   1057:         v->no_cacheable = 0;
                   1058:         v->not_found = 0;
                   1059: 
                   1060:     } else if (r->headers_in.content_length_n >= 0) {
                   1061:         p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
                   1062:         if (p == NULL) {
                   1063:             return NGX_ERROR;
                   1064:         }
                   1065: 
                   1066:         v->len = ngx_sprintf(p, "%O", r->headers_in.content_length_n) - p;
                   1067:         v->data = p;
                   1068:         v->valid = 1;
                   1069:         v->no_cacheable = 0;
                   1070:         v->not_found = 0;
                   1071: 
                   1072:     } else {
                   1073:         v->not_found = 1;
                   1074:     }
                   1075: 
                   1076:     return NGX_OK;
                   1077: }
                   1078: 
                   1079: 
                   1080: static ngx_int_t
                   1081: ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v,
                   1082:     uintptr_t data)
                   1083: {
                   1084:     ngx_http_core_srv_conf_t  *cscf;
                   1085: 
                   1086:     if (r->headers_in.server.len) {
                   1087:         v->len = r->headers_in.server.len;
                   1088:         v->data = r->headers_in.server.data;
                   1089: 
                   1090:     } else {
                   1091:         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
                   1092: 
                   1093:         v->len = cscf->server_name.len;
                   1094:         v->data = cscf->server_name.data;
                   1095:     }
                   1096: 
                   1097:     v->valid = 1;
                   1098:     v->no_cacheable = 0;
                   1099:     v->not_found = 0;
                   1100: 
                   1101:     return NGX_OK;
                   1102: }
                   1103: 
                   1104: 
                   1105: static ngx_int_t
                   1106: ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
                   1107:     ngx_http_variable_value_t *v, uintptr_t data)
                   1108: {
                   1109:     struct sockaddr_in   *sin;
                   1110: #if (NGX_HAVE_INET6)
                   1111:     struct sockaddr_in6  *sin6;
                   1112: #endif
                   1113: 
                   1114:     switch (r->connection->sockaddr->sa_family) {
                   1115: 
                   1116: #if (NGX_HAVE_INET6)
                   1117:     case AF_INET6:
                   1118:         sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
                   1119: 
                   1120:         v->len = sizeof(struct in6_addr);
                   1121:         v->valid = 1;
                   1122:         v->no_cacheable = 0;
                   1123:         v->not_found = 0;
                   1124:         v->data = sin6->sin6_addr.s6_addr;
                   1125: 
                   1126:         break;
                   1127: #endif
                   1128: 
                   1129:     default: /* AF_INET */
                   1130:         sin = (struct sockaddr_in *) r->connection->sockaddr;
                   1131: 
                   1132:         v->len = sizeof(in_addr_t);
                   1133:         v->valid = 1;
                   1134:         v->no_cacheable = 0;
                   1135:         v->not_found = 0;
                   1136:         v->data = (u_char *) &sin->sin_addr;
                   1137: 
                   1138:         break;
                   1139:     }
                   1140: 
                   1141:     return NGX_OK;
                   1142: }
                   1143: 
                   1144: 
                   1145: static ngx_int_t
                   1146: ngx_http_variable_remote_addr(ngx_http_request_t *r,
                   1147:     ngx_http_variable_value_t *v, uintptr_t data)
                   1148: {
                   1149:     v->len = r->connection->addr_text.len;
                   1150:     v->valid = 1;
                   1151:     v->no_cacheable = 0;
                   1152:     v->not_found = 0;
                   1153:     v->data = r->connection->addr_text.data;
                   1154: 
                   1155:     return NGX_OK;
                   1156: }
                   1157: 
                   1158: 
                   1159: static ngx_int_t
                   1160: ngx_http_variable_remote_port(ngx_http_request_t *r,
                   1161:     ngx_http_variable_value_t *v, uintptr_t data)
                   1162: {
                   1163:     ngx_uint_t            port;
                   1164:     struct sockaddr_in   *sin;
                   1165: #if (NGX_HAVE_INET6)
                   1166:     struct sockaddr_in6  *sin6;
                   1167: #endif
                   1168: 
                   1169:     v->len = 0;
                   1170:     v->valid = 1;
                   1171:     v->no_cacheable = 0;
                   1172:     v->not_found = 0;
                   1173: 
                   1174:     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
                   1175:     if (v->data == NULL) {
                   1176:         return NGX_ERROR;
                   1177:     }
                   1178: 
                   1179:     switch (r->connection->sockaddr->sa_family) {
                   1180: 
                   1181: #if (NGX_HAVE_INET6)
                   1182:     case AF_INET6:
                   1183:         sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
                   1184:         port = ntohs(sin6->sin6_port);
                   1185:         break;
                   1186: #endif
                   1187: 
                   1188:     default: /* AF_INET */
                   1189:         sin = (struct sockaddr_in *) r->connection->sockaddr;
                   1190:         port = ntohs(sin->sin_port);
                   1191:         break;
                   1192:     }
                   1193: 
                   1194:     if (port > 0 && port < 65536) {
                   1195:         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
                   1196:     }
                   1197: 
                   1198:     return NGX_OK;
                   1199: }
                   1200: 
                   1201: 
                   1202: static ngx_int_t
                   1203: ngx_http_variable_server_addr(ngx_http_request_t *r,
                   1204:     ngx_http_variable_value_t *v, uintptr_t data)
                   1205: {
                   1206:     ngx_str_t  s;
                   1207:     u_char     addr[NGX_SOCKADDR_STRLEN];
                   1208: 
                   1209:     s.len = NGX_SOCKADDR_STRLEN;
                   1210:     s.data = addr;
                   1211: 
                   1212:     if (ngx_connection_local_sockaddr(r->connection, &s, 0) != NGX_OK) {
                   1213:         return NGX_ERROR;
                   1214:     }
                   1215: 
                   1216:     s.data = ngx_pnalloc(r->pool, s.len);
                   1217:     if (s.data == NULL) {
                   1218:         return NGX_ERROR;
                   1219:     }
                   1220: 
                   1221:     ngx_memcpy(s.data, addr, s.len);
                   1222: 
                   1223:     v->len = s.len;
                   1224:     v->valid = 1;
                   1225:     v->no_cacheable = 0;
                   1226:     v->not_found = 0;
                   1227:     v->data = s.data;
                   1228: 
                   1229:     return NGX_OK;
                   1230: }
                   1231: 
                   1232: 
                   1233: static ngx_int_t
                   1234: ngx_http_variable_server_port(ngx_http_request_t *r,
                   1235:     ngx_http_variable_value_t *v, uintptr_t data)
                   1236: {
                   1237:     ngx_uint_t            port;
                   1238:     struct sockaddr_in   *sin;
                   1239: #if (NGX_HAVE_INET6)
                   1240:     struct sockaddr_in6  *sin6;
                   1241: #endif
                   1242: 
                   1243:     v->len = 0;
                   1244:     v->valid = 1;
                   1245:     v->no_cacheable = 0;
                   1246:     v->not_found = 0;
                   1247: 
                   1248:     if (ngx_connection_local_sockaddr(r->connection, NULL, 0) != NGX_OK) {
                   1249:         return NGX_ERROR;
                   1250:     }
                   1251: 
                   1252:     v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
                   1253:     if (v->data == NULL) {
                   1254:         return NGX_ERROR;
                   1255:     }
                   1256: 
                   1257:     switch (r->connection->local_sockaddr->sa_family) {
                   1258: 
                   1259: #if (NGX_HAVE_INET6)
                   1260:     case AF_INET6:
                   1261:         sin6 = (struct sockaddr_in6 *) r->connection->local_sockaddr;
                   1262:         port = ntohs(sin6->sin6_port);
                   1263:         break;
                   1264: #endif
                   1265: 
                   1266:     default: /* AF_INET */
                   1267:         sin = (struct sockaddr_in *) r->connection->local_sockaddr;
                   1268:         port = ntohs(sin->sin_port);
                   1269:         break;
                   1270:     }
                   1271: 
                   1272:     if (port > 0 && port < 65536) {
                   1273:         v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
                   1274:     }
                   1275: 
                   1276:     return NGX_OK;
                   1277: }
                   1278: 
                   1279: 
                   1280: static ngx_int_t
                   1281: ngx_http_variable_scheme(ngx_http_request_t *r,
                   1282:     ngx_http_variable_value_t *v, uintptr_t data)
                   1283: {
                   1284: #if (NGX_HTTP_SSL)
                   1285: 
                   1286:     if (r->connection->ssl) {
                   1287:         v->len = sizeof("https") - 1;
                   1288:         v->valid = 1;
                   1289:         v->no_cacheable = 0;
                   1290:         v->not_found = 0;
                   1291:         v->data = (u_char *) "https";
                   1292: 
                   1293:         return NGX_OK;
                   1294:     }
                   1295: 
                   1296: #endif
                   1297: 
                   1298:     v->len = sizeof("http") - 1;
                   1299:     v->valid = 1;
                   1300:     v->no_cacheable = 0;
                   1301:     v->not_found = 0;
                   1302:     v->data = (u_char *) "http";
                   1303: 
                   1304:     return NGX_OK;
                   1305: }
                   1306: 
                   1307: 
                   1308: static ngx_int_t
                   1309: ngx_http_variable_https(ngx_http_request_t *r,
                   1310:     ngx_http_variable_value_t *v, uintptr_t data)
                   1311: {
                   1312: #if (NGX_HTTP_SSL)
                   1313: 
                   1314:     if (r->connection->ssl) {
                   1315:         v->len = sizeof("on") - 1;
                   1316:         v->valid = 1;
                   1317:         v->no_cacheable = 0;
                   1318:         v->not_found = 0;
                   1319:         v->data = (u_char *) "on";
                   1320: 
                   1321:         return NGX_OK;
                   1322:     }
                   1323: 
                   1324: #endif
                   1325: 
                   1326:     *v = ngx_http_variable_null_value;
                   1327: 
                   1328:     return NGX_OK;
                   1329: }
                   1330: 
                   1331: 
                   1332: static ngx_int_t
                   1333: ngx_http_variable_is_args(ngx_http_request_t *r,
                   1334:     ngx_http_variable_value_t *v, uintptr_t data)
                   1335: {
                   1336:     v->valid = 1;
                   1337:     v->no_cacheable = 0;
                   1338:     v->not_found = 0;
                   1339: 
                   1340:     if (r->args.len == 0) {
                   1341:         v->len = 0;
                   1342:         v->data = NULL;
                   1343:         return NGX_OK;
                   1344:     }
                   1345: 
                   1346:     v->len = 1;
                   1347:     v->data = (u_char *) "?";
                   1348: 
                   1349:     return NGX_OK;
                   1350: }
                   1351: 
                   1352: 
                   1353: static ngx_int_t
                   1354: ngx_http_variable_document_root(ngx_http_request_t *r,
                   1355:     ngx_http_variable_value_t *v, uintptr_t data)
                   1356: {
                   1357:     ngx_str_t                  path;
                   1358:     ngx_http_core_loc_conf_t  *clcf;
                   1359: 
                   1360:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                   1361: 
                   1362:     if (clcf->root_lengths == NULL) {
                   1363:         v->len = clcf->root.len;
                   1364:         v->valid = 1;
                   1365:         v->no_cacheable = 0;
                   1366:         v->not_found = 0;
                   1367:         v->data = clcf->root.data;
                   1368: 
                   1369:     } else {
                   1370:         if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 0,
                   1371:                                 clcf->root_values->elts)
                   1372:             == NULL)
                   1373:         {
                   1374:             return NGX_ERROR;
                   1375:         }
                   1376: 
                   1377:         if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
                   1378:             return NGX_ERROR;
                   1379:         }
                   1380: 
                   1381:         v->len = path.len;
                   1382:         v->valid = 1;
                   1383:         v->no_cacheable = 0;
                   1384:         v->not_found = 0;
                   1385:         v->data = path.data;
                   1386:     }
                   1387: 
                   1388:     return NGX_OK;
                   1389: }
                   1390: 
                   1391: 
                   1392: static ngx_int_t
                   1393: ngx_http_variable_realpath_root(ngx_http_request_t *r,
                   1394:     ngx_http_variable_value_t *v, uintptr_t data)
                   1395: {
                   1396:     u_char                    *real;
                   1397:     size_t                     len;
                   1398:     ngx_str_t                  path;
                   1399:     ngx_http_core_loc_conf_t  *clcf;
                   1400: #if (NGX_HAVE_MAX_PATH)
                   1401:     u_char                     buffer[NGX_MAX_PATH];
                   1402: #endif
                   1403: 
                   1404:     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                   1405: 
                   1406:     if (clcf->root_lengths == NULL) {
                   1407:         path = clcf->root;
                   1408: 
                   1409:     } else {
                   1410:         if (ngx_http_script_run(r, &path, clcf->root_lengths->elts, 1,
                   1411:                                 clcf->root_values->elts)
                   1412:             == NULL)
                   1413:         {
                   1414:             return NGX_ERROR;
                   1415:         }
                   1416: 
                   1417:         path.data[path.len - 1] = '\0';
                   1418: 
                   1419:         if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, &path, 0) != NGX_OK) {
                   1420:             return NGX_ERROR;
                   1421:         }
                   1422:     }
                   1423: 
                   1424: #if (NGX_HAVE_MAX_PATH)
                   1425:     real = buffer;
                   1426: #else
                   1427:     real = NULL;
                   1428: #endif
                   1429: 
                   1430:     real = ngx_realpath(path.data, real);
                   1431: 
                   1432:     if (real == NULL) {
                   1433:         ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
                   1434:                       ngx_realpath_n " \"%s\" failed", path.data);
                   1435:         return NGX_ERROR;
                   1436:     }
                   1437: 
                   1438:     len = ngx_strlen(real);
                   1439: 
                   1440:     v->data = ngx_pnalloc(r->pool, len);
                   1441:     if (v->data == NULL) {
                   1442: #if !(NGX_HAVE_MAX_PATH)
                   1443:         ngx_free(real);
                   1444: #endif
                   1445:         return NGX_ERROR;
                   1446:     }
                   1447: 
                   1448:     v->len = len;
                   1449:     v->valid = 1;
                   1450:     v->no_cacheable = 0;
                   1451:     v->not_found = 0;
                   1452: 
                   1453:     ngx_memcpy(v->data, real, len);
                   1454: 
                   1455: #if !(NGX_HAVE_MAX_PATH)
                   1456:     ngx_free(real);
                   1457: #endif
                   1458: 
                   1459:     return NGX_OK;
                   1460: }
                   1461: 
                   1462: 
                   1463: static ngx_int_t
                   1464: ngx_http_variable_request_filename(ngx_http_request_t *r,
                   1465:     ngx_http_variable_value_t *v, uintptr_t data)
                   1466: {
                   1467:     size_t     root;
                   1468:     ngx_str_t  path;
                   1469: 
                   1470:     if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
                   1471:         return NGX_ERROR;
                   1472:     }
                   1473: 
                   1474:     /* ngx_http_map_uri_to_path() allocates memory for terminating '\0' */
                   1475: 
                   1476:     v->len = path.len - 1;
                   1477:     v->valid = 1;
                   1478:     v->no_cacheable = 0;
                   1479:     v->not_found = 0;
                   1480:     v->data = path.data;
                   1481: 
                   1482:     return NGX_OK;
                   1483: }
                   1484: 
                   1485: 
                   1486: static ngx_int_t
                   1487: ngx_http_variable_server_name(ngx_http_request_t *r,
                   1488:     ngx_http_variable_value_t *v, uintptr_t data)
                   1489: {
                   1490:     ngx_http_core_srv_conf_t  *cscf;
                   1491: 
                   1492:     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
                   1493: 
                   1494:     v->len = cscf->server_name.len;
                   1495:     v->valid = 1;
                   1496:     v->no_cacheable = 0;
                   1497:     v->not_found = 0;
                   1498:     v->data = cscf->server_name.data;
                   1499: 
                   1500:     return NGX_OK;
                   1501: }
                   1502: 
                   1503: 
                   1504: static ngx_int_t
                   1505: ngx_http_variable_request_method(ngx_http_request_t *r,
                   1506:     ngx_http_variable_value_t *v, uintptr_t data)
                   1507: {
                   1508:     if (r->main->method_name.data) {
                   1509:         v->len = r->main->method_name.len;
                   1510:         v->valid = 1;
                   1511:         v->no_cacheable = 0;
                   1512:         v->not_found = 0;
                   1513:         v->data = r->main->method_name.data;
                   1514: 
                   1515:     } else {
                   1516:         v->not_found = 1;
                   1517:     }
                   1518: 
                   1519:     return NGX_OK;
                   1520: }
                   1521: 
                   1522: 
                   1523: static ngx_int_t
                   1524: ngx_http_variable_remote_user(ngx_http_request_t *r,
                   1525:     ngx_http_variable_value_t *v, uintptr_t data)
                   1526: {
                   1527:     ngx_int_t  rc;
                   1528: 
                   1529:     rc = ngx_http_auth_basic_user(r);
                   1530: 
                   1531:     if (rc == NGX_DECLINED) {
                   1532:         v->not_found = 1;
                   1533:         return NGX_OK;
                   1534:     }
                   1535: 
                   1536:     if (rc == NGX_ERROR) {
                   1537:         return NGX_ERROR;
                   1538:     }
                   1539: 
                   1540:     v->len = r->headers_in.user.len;
                   1541:     v->valid = 1;
                   1542:     v->no_cacheable = 0;
                   1543:     v->not_found = 0;
                   1544:     v->data = r->headers_in.user.data;
                   1545: 
                   1546:     return NGX_OK;
                   1547: }
                   1548: 
                   1549: 
                   1550: static ngx_int_t
                   1551: ngx_http_variable_bytes_sent(ngx_http_request_t *r,
                   1552:     ngx_http_variable_value_t *v, uintptr_t data)
                   1553: {
                   1554:     u_char  *p;
                   1555: 
                   1556:     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
                   1557:     if (p == NULL) {
                   1558:         return NGX_ERROR;
                   1559:     }
                   1560: 
                   1561:     v->len = ngx_sprintf(p, "%O", r->connection->sent) - p;
                   1562:     v->valid = 1;
                   1563:     v->no_cacheable = 0;
                   1564:     v->not_found = 0;
                   1565:     v->data = p;
                   1566: 
                   1567:     return NGX_OK;
                   1568: }
                   1569: 
                   1570: 
                   1571: static ngx_int_t
                   1572: ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
                   1573:     ngx_http_variable_value_t *v, uintptr_t data)
                   1574: {
                   1575:     off_t    sent;
                   1576:     u_char  *p;
                   1577: 
                   1578:     sent = r->connection->sent - r->header_size;
                   1579: 
                   1580:     if (sent < 0) {
                   1581:         sent = 0;
                   1582:     }
                   1583: 
                   1584:     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
                   1585:     if (p == NULL) {
                   1586:         return NGX_ERROR;
                   1587:     }
                   1588: 
                   1589:     v->len = ngx_sprintf(p, "%O", sent) - p;
                   1590:     v->valid = 1;
                   1591:     v->no_cacheable = 0;
                   1592:     v->not_found = 0;
                   1593:     v->data = p;
                   1594: 
                   1595:     return NGX_OK;
                   1596: }
                   1597: 
                   1598: 
                   1599: static ngx_int_t
                   1600: ngx_http_variable_pipe(ngx_http_request_t *r,
                   1601:     ngx_http_variable_value_t *v, uintptr_t data)
                   1602: {
                   1603:     v->data = (u_char *) (r->pipeline ? "p" : ".");
                   1604:     v->len = 1;
                   1605:     v->valid = 1;
                   1606:     v->no_cacheable = 0;
                   1607:     v->not_found = 0;
                   1608: 
                   1609:     return NGX_OK;
                   1610: }
                   1611: 
                   1612: 
                   1613: static ngx_int_t
                   1614: ngx_http_variable_status(ngx_http_request_t *r,
                   1615:     ngx_http_variable_value_t *v, uintptr_t data)
                   1616: {
                   1617:     ngx_uint_t  status;
                   1618: 
                   1619:     v->data = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
                   1620:     if (v->data == NULL) {
                   1621:         return NGX_ERROR;
                   1622:     }
                   1623: 
                   1624:     if (r->err_status) {
                   1625:         status = r->err_status;
                   1626: 
                   1627:     } else if (r->headers_out.status) {
                   1628:         status = r->headers_out.status;
                   1629: 
                   1630:     } else if (r->http_version == NGX_HTTP_VERSION_9) {
                   1631:         status = 9;
                   1632: 
                   1633:     } else {
                   1634:         status = 0;
                   1635:     }
                   1636: 
                   1637:     v->len = ngx_sprintf(v->data, "%03ui", status) - v->data;
                   1638:     v->valid = 1;
                   1639:     v->no_cacheable = 0;
                   1640:     v->not_found = 0;
                   1641: 
                   1642:     return NGX_OK;
                   1643: }
                   1644: 
                   1645: 
                   1646: static ngx_int_t
                   1647: ngx_http_variable_sent_content_type(ngx_http_request_t *r,
                   1648:     ngx_http_variable_value_t *v, uintptr_t data)
                   1649: {
                   1650:     if (r->headers_out.content_type.len) {
                   1651:         v->len = r->headers_out.content_type.len;
                   1652:         v->valid = 1;
                   1653:         v->no_cacheable = 0;
                   1654:         v->not_found = 0;
                   1655:         v->data = r->headers_out.content_type.data;
                   1656: 
                   1657:     } else {
                   1658:         v->not_found = 1;
                   1659:     }
                   1660: 
                   1661:     return NGX_OK;
                   1662: }
                   1663: 
                   1664: 
                   1665: static ngx_int_t
                   1666: ngx_http_variable_sent_content_length(ngx_http_request_t *r,
                   1667:     ngx_http_variable_value_t *v, uintptr_t data)
                   1668: {
                   1669:     u_char  *p;
                   1670: 
                   1671:     if (r->headers_out.content_length) {
                   1672:         v->len = r->headers_out.content_length->value.len;
                   1673:         v->valid = 1;
                   1674:         v->no_cacheable = 0;
                   1675:         v->not_found = 0;
                   1676:         v->data = r->headers_out.content_length->value.data;
                   1677: 
                   1678:         return NGX_OK;
                   1679:     }
                   1680: 
                   1681:     if (r->headers_out.content_length_n >= 0) {
                   1682:         p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
                   1683:         if (p == NULL) {
                   1684:             return NGX_ERROR;
                   1685:         }
                   1686: 
                   1687:         v->len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) - p;
                   1688:         v->valid = 1;
                   1689:         v->no_cacheable = 0;
                   1690:         v->not_found = 0;
                   1691:         v->data = p;
                   1692: 
                   1693:         return NGX_OK;
                   1694:     }
                   1695: 
                   1696:     v->not_found = 1;
                   1697: 
                   1698:     return NGX_OK;
                   1699: }
                   1700: 
                   1701: 
                   1702: static ngx_int_t
                   1703: ngx_http_variable_sent_location(ngx_http_request_t *r,
                   1704:     ngx_http_variable_value_t *v, uintptr_t data)
                   1705: {
                   1706:     ngx_str_t  name;
                   1707: 
                   1708:     if (r->headers_out.location) {
                   1709:         v->len = r->headers_out.location->value.len;
                   1710:         v->valid = 1;
                   1711:         v->no_cacheable = 0;
                   1712:         v->not_found = 0;
                   1713:         v->data = r->headers_out.location->value.data;
                   1714: 
                   1715:         return NGX_OK;
                   1716:     }
                   1717: 
                   1718:     ngx_str_set(&name, "sent_http_location");
                   1719: 
                   1720:     return ngx_http_variable_unknown_header(v, &name,
                   1721:                                             &r->headers_out.headers.part,
                   1722:                                             sizeof("sent_http_") - 1);
                   1723: }
                   1724: 
                   1725: 
                   1726: static ngx_int_t
                   1727: ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
                   1728:     ngx_http_variable_value_t *v, uintptr_t data)
                   1729: {
                   1730:     u_char  *p;
                   1731: 
                   1732:     if (r->headers_out.last_modified) {
                   1733:         v->len = r->headers_out.last_modified->value.len;
                   1734:         v->valid = 1;
                   1735:         v->no_cacheable = 0;
                   1736:         v->not_found = 0;
                   1737:         v->data = r->headers_out.last_modified->value.data;
                   1738: 
                   1739:         return NGX_OK;
                   1740:     }
                   1741: 
                   1742:     if (r->headers_out.last_modified_time >= 0) {
                   1743:         p = ngx_pnalloc(r->pool,
                   1744:                    sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT") - 1);
                   1745:         if (p == NULL) {
                   1746:             return NGX_ERROR;
                   1747:         }
                   1748: 
                   1749:         v->len = ngx_http_time(p, r->headers_out.last_modified_time) - p;
                   1750:         v->valid = 1;
                   1751:         v->no_cacheable = 0;
                   1752:         v->not_found = 0;
                   1753:         v->data = p;
                   1754: 
                   1755:         return NGX_OK;
                   1756:     }
                   1757: 
                   1758:     v->not_found = 1;
                   1759: 
                   1760:     return NGX_OK;
                   1761: }
                   1762: 
                   1763: 
                   1764: static ngx_int_t
                   1765: ngx_http_variable_sent_connection(ngx_http_request_t *r,
                   1766:     ngx_http_variable_value_t *v, uintptr_t data)
                   1767: {
                   1768:     size_t   len;
                   1769:     char    *p;
                   1770: 
                   1771:     if (r->headers_out.status == NGX_HTTP_SWITCHING_PROTOCOLS) {
                   1772:         len = sizeof("upgrade") - 1;
                   1773:         p = "upgrade";
                   1774: 
                   1775:     } else if (r->keepalive) {
                   1776:         len = sizeof("keep-alive") - 1;
                   1777:         p = "keep-alive";
                   1778: 
                   1779:     } else {
                   1780:         len = sizeof("close") - 1;
                   1781:         p = "close";
                   1782:     }
                   1783: 
                   1784:     v->len = len;
                   1785:     v->valid = 1;
                   1786:     v->no_cacheable = 0;
                   1787:     v->not_found = 0;
                   1788:     v->data = (u_char *) p;
                   1789: 
                   1790:     return NGX_OK;
                   1791: }
                   1792: 
                   1793: 
                   1794: static ngx_int_t
                   1795: ngx_http_variable_sent_keep_alive(ngx_http_request_t *r,
                   1796:     ngx_http_variable_value_t *v, uintptr_t data)
                   1797: {
                   1798:     u_char                    *p;
                   1799:     ngx_http_core_loc_conf_t  *clcf;
                   1800: 
                   1801:     if (r->keepalive) {
                   1802:         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                   1803: 
                   1804:         if (clcf->keepalive_header) {
                   1805: 
                   1806:             p = ngx_pnalloc(r->pool, sizeof("timeout=") - 1 + NGX_TIME_T_LEN);
                   1807:             if (p == NULL) {
                   1808:                 return NGX_ERROR;
                   1809:             }
                   1810: 
                   1811:             v->len = ngx_sprintf(p, "timeout=%T", clcf->keepalive_header) - p;
                   1812:             v->valid = 1;
                   1813:             v->no_cacheable = 0;
                   1814:             v->not_found = 0;
                   1815:             v->data = p;
                   1816: 
                   1817:             return NGX_OK;
                   1818:         }
                   1819:     }
                   1820: 
                   1821:     v->not_found = 1;
                   1822: 
                   1823:     return NGX_OK;
                   1824: }
                   1825: 
                   1826: 
                   1827: static ngx_int_t
                   1828: ngx_http_variable_sent_transfer_encoding(ngx_http_request_t *r,
                   1829:     ngx_http_variable_value_t *v, uintptr_t data)
                   1830: {
                   1831:     if (r->chunked) {
                   1832:         v->len = sizeof("chunked") - 1;
                   1833:         v->valid = 1;
                   1834:         v->no_cacheable = 0;
                   1835:         v->not_found = 0;
                   1836:         v->data = (u_char *) "chunked";
                   1837: 
                   1838:     } else {
                   1839:         v->not_found = 1;
                   1840:     }
                   1841: 
                   1842:     return NGX_OK;
                   1843: }
                   1844: 
                   1845: 
                   1846: static ngx_int_t
                   1847: ngx_http_variable_request_completion(ngx_http_request_t *r,
                   1848:     ngx_http_variable_value_t *v, uintptr_t data)
                   1849: {
                   1850:     if (r->request_complete) {
                   1851:         v->len = 2;
                   1852:         v->valid = 1;
                   1853:         v->no_cacheable = 0;
                   1854:         v->not_found = 0;
                   1855:         v->data = (u_char *) "OK";
                   1856: 
                   1857:         return NGX_OK;
                   1858:     }
                   1859: 
                   1860:     v->len = 0;
                   1861:     v->valid = 1;
                   1862:     v->no_cacheable = 0;
                   1863:     v->not_found = 0;
                   1864:     v->data = (u_char *) "";
                   1865: 
                   1866:     return NGX_OK;
                   1867: }
                   1868: 
                   1869: 
                   1870: static ngx_int_t
                   1871: ngx_http_variable_request_body(ngx_http_request_t *r,
                   1872:     ngx_http_variable_value_t *v, uintptr_t data)
                   1873: {
                   1874:     u_char       *p;
                   1875:     size_t        len;
                   1876:     ngx_buf_t    *buf;
                   1877:     ngx_chain_t  *cl;
                   1878: 
                   1879:     if (r->request_body == NULL
                   1880:         || r->request_body->bufs == NULL
                   1881:         || r->request_body->temp_file)
                   1882:     {
                   1883:         v->not_found = 1;
                   1884: 
                   1885:         return NGX_OK;
                   1886:     }
                   1887: 
                   1888:     cl = r->request_body->bufs;
                   1889:     buf = cl->buf;
                   1890: 
                   1891:     if (cl->next == NULL) {
                   1892:         v->len = buf->last - buf->pos;
                   1893:         v->valid = 1;
                   1894:         v->no_cacheable = 0;
                   1895:         v->not_found = 0;
                   1896:         v->data = buf->pos;
                   1897: 
                   1898:         return NGX_OK;
                   1899:     }
                   1900: 
                   1901:     len = buf->last - buf->pos;
                   1902:     cl = cl->next;
                   1903: 
                   1904:     for ( /* void */ ; cl; cl = cl->next) {
                   1905:         buf = cl->buf;
                   1906:         len += buf->last - buf->pos;
                   1907:     }
                   1908: 
                   1909:     p = ngx_pnalloc(r->pool, len);
                   1910:     if (p == NULL) {
                   1911:         return NGX_ERROR;
                   1912:     }
                   1913: 
                   1914:     v->data = p;
                   1915:     cl = r->request_body->bufs;
                   1916: 
                   1917:     for ( /* void */ ; cl; cl = cl->next) {
                   1918:         buf = cl->buf;
                   1919:         p = ngx_cpymem(p, buf->pos, buf->last - buf->pos);
                   1920:     }
                   1921: 
                   1922:     v->len = len;
                   1923:     v->valid = 1;
                   1924:     v->no_cacheable = 0;
                   1925:     v->not_found = 0;
                   1926: 
                   1927:     return NGX_OK;
                   1928: }
                   1929: 
                   1930: 
                   1931: static ngx_int_t
                   1932: ngx_http_variable_request_body_file(ngx_http_request_t *r,
                   1933:     ngx_http_variable_value_t *v, uintptr_t data)
                   1934: {
                   1935:     if (r->request_body == NULL || r->request_body->temp_file == NULL) {
                   1936:         v->not_found = 1;
                   1937: 
                   1938:         return NGX_OK;
                   1939:     }
                   1940: 
                   1941:     v->len = r->request_body->temp_file->file.name.len;
                   1942:     v->valid = 1;
                   1943:     v->no_cacheable = 0;
                   1944:     v->not_found = 0;
                   1945:     v->data = r->request_body->temp_file->file.name.data;
                   1946: 
                   1947:     return NGX_OK;
                   1948: }
                   1949: 
                   1950: 
                   1951: static ngx_int_t
                   1952: ngx_http_variable_request_length(ngx_http_request_t *r,
                   1953:     ngx_http_variable_value_t *v, uintptr_t data)
                   1954: {
                   1955:     u_char  *p;
                   1956: 
                   1957:     p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
                   1958:     if (p == NULL) {
                   1959:         return NGX_ERROR;
                   1960:     }
                   1961: 
                   1962:     v->len = ngx_sprintf(p, "%O", r->request_length) - p;
                   1963:     v->valid = 1;
                   1964:     v->no_cacheable = 0;
                   1965:     v->not_found = 0;
                   1966:     v->data = p;
                   1967: 
                   1968:     return NGX_OK;
                   1969: }
                   1970: 
                   1971: 
                   1972: static ngx_int_t
                   1973: ngx_http_variable_request_time(ngx_http_request_t *r,
                   1974:     ngx_http_variable_value_t *v, uintptr_t data)
                   1975: {
                   1976:     u_char          *p;
                   1977:     ngx_time_t      *tp;
                   1978:     ngx_msec_int_t   ms;
                   1979: 
                   1980:     p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4);
                   1981:     if (p == NULL) {
                   1982:         return NGX_ERROR;
                   1983:     }
                   1984: 
                   1985:     tp = ngx_timeofday();
                   1986: 
                   1987:     ms = (ngx_msec_int_t)
                   1988:              ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec));
                   1989:     ms = ngx_max(ms, 0);
                   1990: 
                   1991:     v->len = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000) - p;
                   1992:     v->valid = 1;
                   1993:     v->no_cacheable = 0;
                   1994:     v->not_found = 0;
                   1995:     v->data = p;
                   1996: 
                   1997:     return NGX_OK;
                   1998: }
                   1999: 
                   2000: 
                   2001: static ngx_int_t
                   2002: ngx_http_variable_connection(ngx_http_request_t *r,
                   2003:     ngx_http_variable_value_t *v, uintptr_t data)
                   2004: {
                   2005:     u_char  *p;
                   2006: 
                   2007:     p = ngx_pnalloc(r->pool, NGX_ATOMIC_T_LEN);
                   2008:     if (p == NULL) {
                   2009:         return NGX_ERROR;
                   2010:     }
                   2011: 
                   2012:     v->len = ngx_sprintf(p, "%uA", r->connection->number) - p;
                   2013:     v->valid = 1;
                   2014:     v->no_cacheable = 0;
                   2015:     v->not_found = 0;
                   2016:     v->data = p;
                   2017: 
                   2018:     return NGX_OK;
                   2019: }
                   2020: 
                   2021: 
                   2022: static ngx_int_t
                   2023: ngx_http_variable_connection_requests(ngx_http_request_t *r,
                   2024:     ngx_http_variable_value_t *v, uintptr_t data)
                   2025: {
                   2026:     u_char  *p;
                   2027: 
                   2028:     p = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
                   2029:     if (p == NULL) {
                   2030:         return NGX_ERROR;
                   2031:     }
                   2032: 
                   2033:     v->len = ngx_sprintf(p, "%ui", r->connection->requests) - p;
                   2034:     v->valid = 1;
                   2035:     v->no_cacheable = 0;
                   2036:     v->not_found = 0;
                   2037:     v->data = p;
                   2038: 
                   2039:     return NGX_OK;
                   2040: }
                   2041: 
                   2042: 
                   2043: static ngx_int_t
                   2044: ngx_http_variable_nginx_version(ngx_http_request_t *r,
                   2045:     ngx_http_variable_value_t *v, uintptr_t data)
                   2046: {
                   2047:     v->len = sizeof(NGINX_VERSION) - 1;
                   2048:     v->valid = 1;
                   2049:     v->no_cacheable = 0;
                   2050:     v->not_found = 0;
                   2051:     v->data = (u_char *) NGINX_VERSION;
                   2052: 
                   2053:     return NGX_OK;
                   2054: }
                   2055: 
                   2056: 
                   2057: static ngx_int_t
                   2058: ngx_http_variable_hostname(ngx_http_request_t *r,
                   2059:     ngx_http_variable_value_t *v, uintptr_t data)
                   2060: {
                   2061:     v->len = ngx_cycle->hostname.len;
                   2062:     v->valid = 1;
                   2063:     v->no_cacheable = 0;
                   2064:     v->not_found = 0;
                   2065:     v->data = ngx_cycle->hostname.data;
                   2066: 
                   2067:     return NGX_OK;
                   2068: }
                   2069: 
                   2070: 
                   2071: static ngx_int_t
                   2072: ngx_http_variable_pid(ngx_http_request_t *r,
                   2073:     ngx_http_variable_value_t *v, uintptr_t data)
                   2074: {
                   2075:     u_char  *p;
                   2076: 
                   2077:     p = ngx_pnalloc(r->pool, NGX_INT64_LEN);
                   2078:     if (p == NULL) {
                   2079:         return NGX_ERROR;
                   2080:     }
                   2081: 
                   2082:     v->len = ngx_sprintf(p, "%P", ngx_pid) - p;
                   2083:     v->valid = 1;
                   2084:     v->no_cacheable = 0;
                   2085:     v->not_found = 0;
                   2086:     v->data = p;
                   2087: 
                   2088:     return NGX_OK;
                   2089: }
                   2090: 
                   2091: 
                   2092: static ngx_int_t
                   2093: ngx_http_variable_msec(ngx_http_request_t *r,
                   2094:     ngx_http_variable_value_t *v, uintptr_t data)
                   2095: {
                   2096:     u_char      *p;
                   2097:     ngx_time_t  *tp;
                   2098: 
                   2099:     p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4);
                   2100:     if (p == NULL) {
                   2101:         return NGX_ERROR;
                   2102:     }
                   2103: 
                   2104:     tp = ngx_timeofday();
                   2105: 
                   2106:     v->len = ngx_sprintf(p, "%T.%03M", tp->sec, tp->msec) - p;
                   2107:     v->valid = 1;
                   2108:     v->no_cacheable = 0;
                   2109:     v->not_found = 0;
                   2110:     v->data = p;
                   2111: 
                   2112:     return NGX_OK;
                   2113: }
                   2114: 
                   2115: 
                   2116: static ngx_int_t
                   2117: ngx_http_variable_time_iso8601(ngx_http_request_t *r,
                   2118:     ngx_http_variable_value_t *v, uintptr_t data)
                   2119: {
                   2120:     u_char  *p;
                   2121: 
                   2122:     p = ngx_pnalloc(r->pool, ngx_cached_http_log_iso8601.len);
                   2123:     if (p == NULL) {
                   2124:         return NGX_ERROR;
                   2125:     }
                   2126: 
                   2127:     ngx_memcpy(p, ngx_cached_http_log_iso8601.data,
                   2128:                ngx_cached_http_log_iso8601.len);
                   2129: 
                   2130:     v->len = ngx_cached_http_log_iso8601.len;
                   2131:     v->valid = 1;
                   2132:     v->no_cacheable = 0;
                   2133:     v->not_found = 0;
                   2134:     v->data = p;
                   2135: 
                   2136:     return NGX_OK;
                   2137: }
                   2138: 
                   2139: 
                   2140: static ngx_int_t
                   2141: ngx_http_variable_time_local(ngx_http_request_t *r,
                   2142:     ngx_http_variable_value_t *v, uintptr_t data)
                   2143: {
                   2144:     u_char  *p;
                   2145: 
                   2146:     p = ngx_pnalloc(r->pool, ngx_cached_http_log_time.len);
                   2147:     if (p == NULL) {
                   2148:         return NGX_ERROR;
                   2149:     }
                   2150: 
                   2151:     ngx_memcpy(p, ngx_cached_http_log_time.data, ngx_cached_http_log_time.len);
                   2152: 
                   2153:     v->len = ngx_cached_http_log_time.len;
                   2154:     v->valid = 1;
                   2155:     v->no_cacheable = 0;
                   2156:     v->not_found = 0;
                   2157:     v->data = p;
                   2158: 
                   2159:     return NGX_OK;
                   2160: }
                   2161: 
                   2162: 
                   2163: void *
                   2164: ngx_http_map_find(ngx_http_request_t *r, ngx_http_map_t *map, ngx_str_t *match)
                   2165: {
                   2166:     void        *value;
                   2167:     u_char      *low;
                   2168:     size_t       len;
                   2169:     ngx_uint_t   key;
                   2170: 
                   2171:     len = match->len;
                   2172: 
                   2173:     if (len) {
                   2174:         low = ngx_pnalloc(r->pool, len);
                   2175:         if (low == NULL) {
                   2176:             return NULL;
                   2177:         }
                   2178: 
                   2179:     } else {
                   2180:         low = NULL;
                   2181:     }
                   2182: 
                   2183:     key = ngx_hash_strlow(low, match->data, len);
                   2184: 
                   2185:     value = ngx_hash_find_combined(&map->hash, key, low, len);
                   2186:     if (value) {
                   2187:         return value;
                   2188:     }
                   2189: 
                   2190: #if (NGX_PCRE)
                   2191: 
                   2192:     if (len && map->nregex) {
                   2193:         ngx_int_t              n;
                   2194:         ngx_uint_t             i;
                   2195:         ngx_http_map_regex_t  *reg;
                   2196: 
                   2197:         reg = map->regex;
                   2198: 
                   2199:         for (i = 0; i < map->nregex; i++) {
                   2200: 
                   2201:             n = ngx_http_regex_exec(r, reg[i].regex, match);
                   2202: 
                   2203:             if (n == NGX_OK) {
                   2204:                 return reg[i].value;
                   2205:             }
                   2206: 
                   2207:             if (n == NGX_DECLINED) {
                   2208:                 continue;
                   2209:             }
                   2210: 
                   2211:             /* NGX_ERROR */
                   2212: 
                   2213:             return NULL;
                   2214:         }
                   2215:     }
                   2216: 
                   2217: #endif
                   2218: 
                   2219:     return NULL;
                   2220: }
                   2221: 
                   2222: 
                   2223: #if (NGX_PCRE)
                   2224: 
                   2225: static ngx_int_t
                   2226: ngx_http_variable_not_found(ngx_http_request_t *r, ngx_http_variable_value_t *v,
                   2227:     uintptr_t data)
                   2228: {
                   2229:     v->not_found = 1;
                   2230:     return NGX_OK;
                   2231: }
                   2232: 
                   2233: 
                   2234: ngx_http_regex_t *
                   2235: ngx_http_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc)
                   2236: {
                   2237:     u_char                     *p;
                   2238:     size_t                      size;
                   2239:     ngx_str_t                   name;
                   2240:     ngx_uint_t                  i, n;
                   2241:     ngx_http_variable_t        *v;
                   2242:     ngx_http_regex_t           *re;
                   2243:     ngx_http_regex_variable_t  *rv;
                   2244:     ngx_http_core_main_conf_t  *cmcf;
                   2245: 
                   2246:     rc->pool = cf->pool;
                   2247: 
                   2248:     if (ngx_regex_compile(rc) != NGX_OK) {
                   2249:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err);
                   2250:         return NULL;
                   2251:     }
                   2252: 
                   2253:     re = ngx_pcalloc(cf->pool, sizeof(ngx_http_regex_t));
                   2254:     if (re == NULL) {
                   2255:         return NULL;
                   2256:     }
                   2257: 
                   2258:     re->regex = rc->regex;
                   2259:     re->ncaptures = rc->captures;
                   2260: 
                   2261:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
                   2262:     cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures);
                   2263: 
                   2264:     n = (ngx_uint_t) rc->named_captures;
                   2265: 
                   2266:     if (n == 0) {
                   2267:         return re;
                   2268:     }
                   2269: 
                   2270:     rv = ngx_palloc(rc->pool, n * sizeof(ngx_http_regex_variable_t));
                   2271:     if (rv == NULL) {
                   2272:         return NULL;
                   2273:     }
                   2274: 
                   2275:     re->variables = rv;
                   2276:     re->nvariables = n;
                   2277:     re->name = rc->pattern;
                   2278: 
                   2279:     size = rc->name_size;
                   2280:     p = rc->names;
                   2281: 
                   2282:     for (i = 0; i < n; i++) {
                   2283:         rv[i].capture = 2 * ((p[0] << 8) + p[1]);
                   2284: 
                   2285:         name.data = &p[2];
                   2286:         name.len = ngx_strlen(name.data);
                   2287: 
                   2288:         v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
                   2289:         if (v == NULL) {
                   2290:             return NULL;
                   2291:         }
                   2292: 
                   2293:         rv[i].index = ngx_http_get_variable_index(cf, &name);
                   2294:         if (rv[i].index == NGX_ERROR) {
                   2295:             return NULL;
                   2296:         }
                   2297: 
                   2298:         v->get_handler = ngx_http_variable_not_found;
                   2299: 
                   2300:         p += size;
                   2301:     }
                   2302: 
                   2303:     return re;
                   2304: }
                   2305: 
                   2306: 
                   2307: ngx_int_t
                   2308: ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, ngx_str_t *s)
                   2309: {
                   2310:     ngx_int_t                   rc, index;
                   2311:     ngx_uint_t                  i, n, len;
                   2312:     ngx_http_variable_value_t  *vv;
                   2313:     ngx_http_core_main_conf_t  *cmcf;
                   2314: 
                   2315:     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
                   2316: 
                   2317:     if (re->ncaptures) {
                   2318:         len = cmcf->ncaptures;
                   2319: 
                   2320:         if (r->captures == NULL) {
                   2321:             r->captures = ngx_palloc(r->pool, len * sizeof(int));
                   2322:             if (r->captures == NULL) {
                   2323:                 return NGX_ERROR;
                   2324:             }
                   2325:         }
                   2326: 
                   2327:     } else {
                   2328:         len = 0;
                   2329:     }
                   2330: 
                   2331:     rc = ngx_regex_exec(re->regex, s, r->captures, len);
                   2332: 
                   2333:     if (rc == NGX_REGEX_NO_MATCHED) {
                   2334:         return NGX_DECLINED;
                   2335:     }
                   2336: 
                   2337:     if (rc < 0) {
                   2338:         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                   2339:                       ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
                   2340:                       rc, s, &re->name);
                   2341:         return NGX_ERROR;
                   2342:     }
                   2343: 
                   2344:     for (i = 0; i < re->nvariables; i++) {
                   2345: 
                   2346:         n = re->variables[i].capture;
                   2347:         index = re->variables[i].index;
                   2348:         vv = &r->variables[index];
                   2349: 
                   2350:         vv->len = r->captures[n + 1] - r->captures[n];
                   2351:         vv->valid = 1;
                   2352:         vv->no_cacheable = 0;
                   2353:         vv->not_found = 0;
                   2354:         vv->data = &s->data[r->captures[n]];
                   2355: 
                   2356: #if (NGX_DEBUG)
                   2357:         {
                   2358:         ngx_http_variable_t  *v;
                   2359: 
                   2360:         v = cmcf->variables.elts;
                   2361: 
                   2362:         ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   2363:                        "http regex set $%V to \"%*s\"",
                   2364:                        &v[index].name, vv->len, vv->data);
                   2365:         }
                   2366: #endif
                   2367:     }
                   2368: 
                   2369:     r->ncaptures = rc * 2;
                   2370:     r->captures_data = s->data;
                   2371: 
                   2372:     return NGX_OK;
                   2373: }
                   2374: 
                   2375: #endif
                   2376: 
                   2377: 
                   2378: ngx_int_t
                   2379: ngx_http_variables_add_core_vars(ngx_conf_t *cf)
                   2380: {
                   2381:     ngx_int_t                   rc;
                   2382:     ngx_http_variable_t        *cv, *v;
                   2383:     ngx_http_core_main_conf_t  *cmcf;
                   2384: 
                   2385:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
                   2386: 
                   2387:     cmcf->variables_keys = ngx_pcalloc(cf->temp_pool,
                   2388:                                        sizeof(ngx_hash_keys_arrays_t));
                   2389:     if (cmcf->variables_keys == NULL) {
                   2390:         return NGX_ERROR;
                   2391:     }
                   2392: 
                   2393:     cmcf->variables_keys->pool = cf->pool;
                   2394:     cmcf->variables_keys->temp_pool = cf->pool;
                   2395: 
                   2396:     if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL)
                   2397:         != NGX_OK)
                   2398:     {
                   2399:         return NGX_ERROR;
                   2400:     }
                   2401: 
                   2402:     for (cv = ngx_http_core_variables; cv->name.len; cv++) {
                   2403:         v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));
                   2404:         if (v == NULL) {
                   2405:             return NGX_ERROR;
                   2406:         }
                   2407: 
                   2408:         *v = *cv;
                   2409: 
                   2410:         rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v,
                   2411:                               NGX_HASH_READONLY_KEY);
                   2412: 
                   2413:         if (rc == NGX_OK) {
                   2414:             continue;
                   2415:         }
                   2416: 
                   2417:         if (rc == NGX_BUSY) {
                   2418:             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                   2419:                                "conflicting variable name \"%V\"", &v->name);
                   2420:         }
                   2421: 
                   2422:         return NGX_ERROR;
                   2423:     }
                   2424: 
                   2425:     return NGX_OK;
                   2426: }
                   2427: 
                   2428: 
                   2429: ngx_int_t
                   2430: ngx_http_variables_init_vars(ngx_conf_t *cf)
                   2431: {
                   2432:     ngx_uint_t                  i, n;
                   2433:     ngx_hash_key_t             *key;
                   2434:     ngx_hash_init_t             hash;
                   2435:     ngx_http_variable_t        *v, *av;
                   2436:     ngx_http_core_main_conf_t  *cmcf;
                   2437: 
                   2438:     /* set the handlers for the indexed http variables */
                   2439: 
                   2440:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
                   2441: 
                   2442:     v = cmcf->variables.elts;
                   2443:     key = cmcf->variables_keys->keys.elts;
                   2444: 
                   2445:     for (i = 0; i < cmcf->variables.nelts; i++) {
                   2446: 
                   2447:         for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {
                   2448: 
                   2449:             av = key[n].value;
                   2450: 
                   2451:             if (av->get_handler
                   2452:                 && v[i].name.len == key[n].key.len
                   2453:                 && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len)
                   2454:                    == 0)
                   2455:             {
                   2456:                 v[i].get_handler = av->get_handler;
                   2457:                 v[i].data = av->data;
                   2458: 
                   2459:                 av->flags |= NGX_HTTP_VAR_INDEXED;
                   2460:                 v[i].flags = av->flags;
                   2461: 
                   2462:                 av->index = i;
                   2463: 
                   2464:                 goto next;
                   2465:             }
                   2466:         }
                   2467: 
                   2468:         if (ngx_strncmp(v[i].name.data, "http_", 5) == 0) {
                   2469:             v[i].get_handler = ngx_http_variable_unknown_header_in;
                   2470:             v[i].data = (uintptr_t) &v[i].name;
                   2471: 
                   2472:             continue;
                   2473:         }
                   2474: 
                   2475:         if (ngx_strncmp(v[i].name.data, "sent_http_", 10) == 0) {
                   2476:             v[i].get_handler = ngx_http_variable_unknown_header_out;
                   2477:             v[i].data = (uintptr_t) &v[i].name;
                   2478: 
                   2479:             continue;
                   2480:         }
                   2481: 
                   2482:         if (ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0) {
                   2483:             v[i].get_handler = ngx_http_upstream_header_variable;
                   2484:             v[i].data = (uintptr_t) &v[i].name;
                   2485:             v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;
                   2486: 
                   2487:             continue;
                   2488:         }
                   2489: 
                   2490:         if (ngx_strncmp(v[i].name.data, "cookie_", 7) == 0) {
                   2491:             v[i].get_handler = ngx_http_variable_cookie;
                   2492:             v[i].data = (uintptr_t) &v[i].name;
                   2493: 
                   2494:             continue;
                   2495:         }
                   2496: 
                   2497:         if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) {
                   2498:             v[i].get_handler = ngx_http_variable_argument;
                   2499:             v[i].data = (uintptr_t) &v[i].name;
                   2500:             v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;
                   2501: 
                   2502:             continue;
                   2503:         }
                   2504: 
                   2505:         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                   2506:                       "unknown \"%V\" variable", &v[i].name);
                   2507: 
                   2508:         return NGX_ERROR;
                   2509: 
                   2510:     next:
                   2511:         continue;
                   2512:     }
                   2513: 
                   2514: 
                   2515:     for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {
                   2516:         av = key[n].value;
                   2517: 
                   2518:         if (av->flags & NGX_HTTP_VAR_NOHASH) {
                   2519:             key[n].key.data = NULL;
                   2520:         }
                   2521:     }
                   2522: 
                   2523: 
                   2524:     hash.hash = &cmcf->variables_hash;
                   2525:     hash.key = ngx_hash_key;
                   2526:     hash.max_size = cmcf->variables_hash_max_size;
                   2527:     hash.bucket_size = cmcf->variables_hash_bucket_size;
                   2528:     hash.name = "variables_hash";
                   2529:     hash.pool = cf->pool;
                   2530:     hash.temp_pool = NULL;
                   2531: 
                   2532:     if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts,
                   2533:                       cmcf->variables_keys->keys.nelts)
                   2534:         != NGX_OK)
                   2535:     {
                   2536:         return NGX_ERROR;
                   2537:     }
                   2538: 
                   2539:     cmcf->variables_keys = NULL;
                   2540: 
                   2541:     return NGX_OK;
                   2542: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>