Mercurial > hg > nginx-quic
comparison src/http/modules/ngx_http_fastcgi_module.c @ 2443:a8697cc12b3a
fastcgi_split_path_info
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 16 Jan 2009 13:21:20 +0000 |
parents | d3454e719bbb |
children | 84f2bef92007 |
comparison
equal
deleted
inserted
replaced
2442:6978f3827a5c | 2443:a8697cc12b3a |
---|---|
20 ngx_array_t *params_source; | 20 ngx_array_t *params_source; |
21 ngx_array_t *catch_stderr; | 21 ngx_array_t *catch_stderr; |
22 | 22 |
23 ngx_array_t *fastcgi_lengths; | 23 ngx_array_t *fastcgi_lengths; |
24 ngx_array_t *fastcgi_values; | 24 ngx_array_t *fastcgi_values; |
25 | |
26 #if (NGX_PCRE) | |
27 ngx_regex_t *split_regex; | |
28 ngx_str_t split_name; | |
29 #endif | |
25 } ngx_http_fastcgi_loc_conf_t; | 30 } ngx_http_fastcgi_loc_conf_t; |
26 | 31 |
27 | 32 |
28 typedef enum { | 33 typedef enum { |
29 ngx_http_fastcgi_st_version = 0, | 34 ngx_http_fastcgi_st_version = 0, |
54 size_t padding; | 59 size_t padding; |
55 | 60 |
56 ngx_uint_t fastcgi_stdout; /* unsigned :1 */ | 61 ngx_uint_t fastcgi_stdout; /* unsigned :1 */ |
57 | 62 |
58 ngx_array_t *split_parts; | 63 ngx_array_t *split_parts; |
64 | |
65 ngx_str_t script_name; | |
66 ngx_str_t path_info; | |
59 } ngx_http_fastcgi_ctx_t; | 67 } ngx_http_fastcgi_ctx_t; |
60 | 68 |
61 | 69 |
62 #define NGX_HTTP_FASTCGI_RESPONDER 1 | 70 #define NGX_HTTP_FASTCGI_RESPONDER 1 |
63 | 71 |
123 static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf); | 131 static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf); |
124 static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, | 132 static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, |
125 void *parent, void *child); | 133 void *parent, void *child); |
126 static ngx_int_t ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, | 134 static ngx_int_t ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, |
127 ngx_http_variable_value_t *v, uintptr_t data); | 135 ngx_http_variable_value_t *v, uintptr_t data); |
136 static ngx_int_t ngx_http_fastcgi_path_info_variable(ngx_http_request_t *r, | |
137 ngx_http_variable_value_t *v, uintptr_t data); | |
138 static ngx_int_t ngx_http_fastcgi_split(ngx_http_request_t *r, | |
139 ngx_http_fastcgi_ctx_t *f, ngx_http_fastcgi_loc_conf_t *flcf); | |
128 | 140 |
129 static char *ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, | 141 static char *ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, |
130 void *conf); | 142 void *conf); |
143 static char *ngx_http_fastcgi_split_path_info(ngx_conf_t *cf, | |
144 ngx_command_t *cmd, void *conf); | |
131 static char *ngx_http_fastcgi_store(ngx_conf_t *cf, ngx_command_t *cmd, | 145 static char *ngx_http_fastcgi_store(ngx_conf_t *cf, ngx_command_t *cmd, |
132 void *conf); | 146 void *conf); |
133 static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, | 147 static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, |
134 void *data); | 148 void *data); |
135 | 149 |
167 { ngx_string("fastcgi_index"), | 181 { ngx_string("fastcgi_index"), |
168 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | 182 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
169 ngx_conf_set_str_slot, | 183 ngx_conf_set_str_slot, |
170 NGX_HTTP_LOC_CONF_OFFSET, | 184 NGX_HTTP_LOC_CONF_OFFSET, |
171 offsetof(ngx_http_fastcgi_loc_conf_t, index), | 185 offsetof(ngx_http_fastcgi_loc_conf_t, index), |
186 NULL }, | |
187 | |
188 { ngx_string("fastcgi_split_path_info"), | |
189 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
190 ngx_http_fastcgi_split_path_info, | |
191 NGX_HTTP_LOC_CONF_OFFSET, | |
192 0, | |
172 NULL }, | 193 NULL }, |
173 | 194 |
174 { ngx_string("fastcgi_store"), | 195 { ngx_string("fastcgi_store"), |
175 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | 196 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
176 ngx_http_fastcgi_store, | 197 ngx_http_fastcgi_store, |
388 1 }, /* request_id_lo */ | 409 1 }, /* request_id_lo */ |
389 | 410 |
390 }; | 411 }; |
391 | 412 |
392 | 413 |
393 static ngx_str_t ngx_http_fastcgi_script_name = | 414 static ngx_http_variable_t ngx_http_fastcgi_vars[] = { |
394 ngx_string("fastcgi_script_name"); | 415 |
416 { ngx_string("fastcgi_script_name"), NULL, | |
417 ngx_http_fastcgi_script_name_variable, 0, | |
418 NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, | |
419 | |
420 { ngx_string("fastcgi_path_info"), NULL, | |
421 ngx_http_fastcgi_path_info_variable, 0, | |
422 NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, | |
423 | |
424 { ngx_null_string, NULL, NULL, 0, 0, 0 } | |
425 }; | |
395 | 426 |
396 | 427 |
397 static ngx_str_t ngx_http_fastcgi_hide_headers[] = { | 428 static ngx_str_t ngx_http_fastcgi_hide_headers[] = { |
398 ngx_string("Status"), | 429 ngx_string("Status"), |
399 ngx_string("X-Accel-Expires"), | 430 ngx_string("X-Accel-Expires"), |
408 static ngx_int_t | 439 static ngx_int_t |
409 ngx_http_fastcgi_handler(ngx_http_request_t *r) | 440 ngx_http_fastcgi_handler(ngx_http_request_t *r) |
410 { | 441 { |
411 ngx_int_t rc; | 442 ngx_int_t rc; |
412 ngx_http_upstream_t *u; | 443 ngx_http_upstream_t *u; |
444 ngx_http_fastcgi_ctx_t *f; | |
413 ngx_http_fastcgi_loc_conf_t *flcf; | 445 ngx_http_fastcgi_loc_conf_t *flcf; |
414 | 446 |
415 if (r->subrequest_in_memory) { | 447 if (r->subrequest_in_memory) { |
416 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | 448 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, |
417 "ngx_http_fastcgi_module does not support " | 449 "ngx_http_fastcgi_module does not support " |
418 "subrequest in memory"); | 450 "subrequest in memory"); |
419 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 451 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
420 } | 452 } |
421 | 453 |
422 ngx_http_set_ctx(r, NULL, ngx_http_fastcgi_module); | 454 f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t)); |
455 if (f == NULL) { | |
456 return NGX_ERROR; | |
457 } | |
458 | |
459 ngx_http_set_ctx(r, f, ngx_http_fastcgi_module); | |
423 | 460 |
424 u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); | 461 u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); |
425 if (u == NULL) { | 462 if (u == NULL) { |
426 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 463 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
427 } | 464 } |
931 | 968 |
932 f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); | 969 f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); |
933 | 970 |
934 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); | 971 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); |
935 | 972 |
936 if (f == NULL) { | |
937 f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t)); | |
938 if (f == NULL) { | |
939 return NGX_ERROR; | |
940 } | |
941 | |
942 ngx_http_set_ctx(r, f, ngx_http_fastcgi_module); | |
943 } | |
944 | |
945 u = r->upstream; | 973 u = r->upstream; |
946 | 974 |
947 for ( ;; ) { | 975 for ( ;; ) { |
948 | 976 |
949 if (f->state < ngx_http_fastcgi_st_data) { | 977 if (f->state < ngx_http_fastcgi_st_data) { |
1664 | 1692 |
1665 | 1693 |
1666 static ngx_int_t | 1694 static ngx_int_t |
1667 ngx_http_fastcgi_add_variables(ngx_conf_t *cf) | 1695 ngx_http_fastcgi_add_variables(ngx_conf_t *cf) |
1668 { | 1696 { |
1669 ngx_http_variable_t *var; | 1697 ngx_http_variable_t *var, *v; |
1670 | 1698 |
1671 var = ngx_http_add_variable(cf, &ngx_http_fastcgi_script_name, | 1699 for (v = ngx_http_fastcgi_vars; v->name.len; v++) { |
1672 NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE); | 1700 var = ngx_http_add_variable(cf, &v->name, v->flags); |
1673 if (var == NULL) { | 1701 if (var == NULL) { |
1674 return NGX_ERROR; | 1702 return NGX_ERROR; |
1675 } | 1703 } |
1676 | 1704 |
1677 var->get_handler = ngx_http_fastcgi_script_name_variable; | 1705 var->get_handler = v->get_handler; |
1706 var->data = v->data; | |
1707 } | |
1678 | 1708 |
1679 return NGX_OK; | 1709 return NGX_OK; |
1680 } | 1710 } |
1681 | 1711 |
1682 | 1712 |
1931 if (conf->fastcgi_lengths == NULL) { | 1961 if (conf->fastcgi_lengths == NULL) { |
1932 conf->fastcgi_lengths = prev->fastcgi_lengths; | 1962 conf->fastcgi_lengths = prev->fastcgi_lengths; |
1933 conf->fastcgi_values = prev->fastcgi_values; | 1963 conf->fastcgi_values = prev->fastcgi_values; |
1934 } | 1964 } |
1935 | 1965 |
1966 #if (NGX_PCRE) | |
1967 if (conf->split_regex == NULL) { | |
1968 conf->split_regex = prev->split_regex; | |
1969 conf->split_name = prev->split_name; | |
1970 } | |
1971 #endif | |
1972 | |
1936 if (conf->params_source == NULL) { | 1973 if (conf->params_source == NULL) { |
1937 conf->flushes = prev->flushes; | 1974 conf->flushes = prev->flushes; |
1938 conf->params_len = prev->params_len; | 1975 conf->params_len = prev->params_len; |
1939 conf->params = prev->params; | 1976 conf->params = prev->params; |
1940 conf->params_source = prev->params_source; | 1977 conf->params_source = prev->params_source; |
2069 static ngx_int_t | 2106 static ngx_int_t |
2070 ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, | 2107 ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, |
2071 ngx_http_variable_value_t *v, uintptr_t data) | 2108 ngx_http_variable_value_t *v, uintptr_t data) |
2072 { | 2109 { |
2073 u_char *p; | 2110 u_char *p; |
2111 ngx_http_fastcgi_ctx_t *f; | |
2074 ngx_http_fastcgi_loc_conf_t *flcf; | 2112 ngx_http_fastcgi_loc_conf_t *flcf; |
2075 | 2113 |
2076 if (r->uri.len) { | 2114 f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); |
2115 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); | |
2116 | |
2117 if (ngx_http_fastcgi_split(r, f, flcf) != NGX_OK) { | |
2118 return NGX_ERROR; | |
2119 } | |
2120 | |
2121 if (f->script_name.len == 0 | |
2122 || f->script_name.data[f->script_name.len - 1] != '/') | |
2123 { | |
2124 v->len = f->script_name.len; | |
2077 v->valid = 1; | 2125 v->valid = 1; |
2078 v->no_cacheable = 0; | 2126 v->no_cacheable = 0; |
2079 v->not_found = 0; | 2127 v->not_found = 0; |
2080 | 2128 v->data = f->script_name.data; |
2081 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); | |
2082 | |
2083 if (r->uri.data[r->uri.len - 1] != '/') { | |
2084 v->len = r->uri.len; | |
2085 v->data = r->uri.data; | |
2086 return NGX_OK; | |
2087 } | |
2088 | |
2089 v->len = r->uri.len + flcf->index.len; | |
2090 | |
2091 v->data = ngx_pnalloc(r->pool, v->len); | |
2092 if (v->data == NULL) { | |
2093 return NGX_ERROR; | |
2094 } | |
2095 | |
2096 p = ngx_copy(v->data, r->uri.data, r->uri.len); | |
2097 ngx_memcpy(p, flcf->index.data, flcf->index.len); | |
2098 | |
2099 } else { | |
2100 v->len = 0; | |
2101 v->valid = 1; | |
2102 v->no_cacheable = 0; | |
2103 v->not_found = 0; | |
2104 v->data = NULL; | |
2105 | 2129 |
2106 return NGX_OK; | 2130 return NGX_OK; |
2107 } | 2131 } |
2108 | 2132 |
2133 v->len = f->script_name.len + flcf->index.len; | |
2134 | |
2135 v->data = ngx_pnalloc(r->pool, v->len); | |
2136 if (v->data == NULL) { | |
2137 return NGX_ERROR; | |
2138 } | |
2139 | |
2140 p = ngx_copy(v->data, f->script_name.data, f->script_name.len); | |
2141 ngx_memcpy(p, flcf->index.data, flcf->index.len); | |
2142 | |
2109 return NGX_OK; | 2143 return NGX_OK; |
2144 } | |
2145 | |
2146 | |
2147 static ngx_int_t | |
2148 ngx_http_fastcgi_path_info_variable(ngx_http_request_t *r, | |
2149 ngx_http_variable_value_t *v, uintptr_t data) | |
2150 { | |
2151 ngx_http_fastcgi_ctx_t *f; | |
2152 ngx_http_fastcgi_loc_conf_t *flcf; | |
2153 | |
2154 f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); | |
2155 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); | |
2156 | |
2157 if (ngx_http_fastcgi_split(r, f, flcf) != NGX_OK) { | |
2158 return NGX_ERROR; | |
2159 } | |
2160 | |
2161 v->len = f->path_info.len; | |
2162 v->valid = 1; | |
2163 v->no_cacheable = 0; | |
2164 v->not_found = 0; | |
2165 v->data = f->path_info.data; | |
2166 | |
2167 return NGX_OK; | |
2168 } | |
2169 | |
2170 | |
2171 static ngx_int_t | |
2172 ngx_http_fastcgi_split(ngx_http_request_t *r, ngx_http_fastcgi_ctx_t *f, | |
2173 ngx_http_fastcgi_loc_conf_t *flcf) | |
2174 { | |
2175 #if (NGX_PCRE) | |
2176 ngx_int_t n; | |
2177 int captures[(1 + 2) * 3]; | |
2178 | |
2179 if (f->script_name.len) { | |
2180 return NGX_OK; | |
2181 } | |
2182 | |
2183 if (flcf->split_regex == NULL) { | |
2184 f->script_name = r->uri; | |
2185 return NGX_OK; | |
2186 } | |
2187 | |
2188 n = ngx_regex_exec(flcf->split_regex, &r->uri, captures, (1 + 2) * 3); | |
2189 | |
2190 if (n == NGX_REGEX_NO_MATCHED) { | |
2191 f->script_name = r->uri; | |
2192 return NGX_OK; | |
2193 } | |
2194 | |
2195 if (n < 0) { | |
2196 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
2197 ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"", | |
2198 n, &r->uri, &flcf->split_name); | |
2199 return NGX_ERROR; | |
2200 } | |
2201 | |
2202 /* match */ | |
2203 | |
2204 f->script_name.len = captures[3] - captures[2]; | |
2205 f->script_name.data = r->uri.data; | |
2206 | |
2207 f->path_info.len = captures[5] - captures[4]; | |
2208 f->path_info.data = r->uri.data + f->script_name.len; | |
2209 | |
2210 return NGX_OK; | |
2211 | |
2212 #else | |
2213 | |
2214 f->script_name = r->uri; | |
2215 | |
2216 return NGX_OK; | |
2217 | |
2218 #endif | |
2110 } | 2219 } |
2111 | 2220 |
2112 | 2221 |
2113 static char * | 2222 static char * |
2114 ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 2223 ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
2166 if (clcf->name.data[clcf->name.len - 1] == '/') { | 2275 if (clcf->name.data[clcf->name.len - 1] == '/') { |
2167 clcf->auto_redirect = 1; | 2276 clcf->auto_redirect = 1; |
2168 } | 2277 } |
2169 | 2278 |
2170 return NGX_CONF_OK; | 2279 return NGX_CONF_OK; |
2280 } | |
2281 | |
2282 | |
2283 static char * | |
2284 ngx_http_fastcgi_split_path_info(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
2285 { | |
2286 #if (NGX_PCRE) | |
2287 ngx_http_fastcgi_loc_conf_t *flcf = conf; | |
2288 | |
2289 ngx_int_t n; | |
2290 ngx_str_t *value, err; | |
2291 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
2292 | |
2293 value = cf->args->elts; | |
2294 | |
2295 flcf->split_name = value[1]; | |
2296 | |
2297 err.len = NGX_MAX_CONF_ERRSTR; | |
2298 err.data = errstr; | |
2299 | |
2300 flcf->split_regex = ngx_regex_compile(&value[1], 0, cf->pool, &err); | |
2301 | |
2302 if (flcf->split_regex == NULL) { | |
2303 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); | |
2304 return NGX_CONF_ERROR; | |
2305 } | |
2306 | |
2307 n = ngx_regex_capture_count(flcf->split_regex); | |
2308 | |
2309 if (n < 0) { | |
2310 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
2311 ngx_regex_capture_count_n " failed for " | |
2312 "pattern \"%V\"", &value[1]); | |
2313 return NGX_CONF_ERROR; | |
2314 } | |
2315 | |
2316 if (n != 2) { | |
2317 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
2318 "pattern \"%V\" must have 2 captures", &value[1]); | |
2319 return NGX_CONF_ERROR; | |
2320 } | |
2321 | |
2322 return NGX_CONF_OK; | |
2323 | |
2324 #else | |
2325 | |
2326 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
2327 "\"%V\" requires PCRE library", &cmd->name); | |
2328 return NGX_CONF_ERROR; | |
2329 | |
2330 #endif | |
2171 } | 2331 } |
2172 | 2332 |
2173 | 2333 |
2174 static char * | 2334 static char * |
2175 ngx_http_fastcgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 2335 ngx_http_fastcgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |