comparison src/http/modules/ngx_http_fastcgi_module.c @ 438:ce4f9ff90bfa NGINX_0_7_31

nginx 0.7.31 *) Change: now the "try_files" directive tests files only and ignores directories. *) Feature: the "fastcgi_split_path_info" directive. *) Bugfixes in an "Expect" request header line support. *) Bugfixes in geo ranges. *) Bugfix: in a miss case ngx_http_memcached_module returned the "END" line as response body instead of default 404 page body; the bug had appeared in 0.7.18. Thanks to Maxim Dounin. *) Bugfix: while SMTP proxying nginx issued message "250 2.0.0 OK" instead of "235 2.0.0 OK"; the bug had appeared in 0.7.22. Thanks to Maxim Dounin.
author Igor Sysoev <http://sysoev.ru>
date Mon, 19 Jan 2009 00:00:00 +0300
parents dc98ed169c03
children 6281966854a5
comparison
equal deleted inserted replaced
437:5da91f7cde93 438:ce4f9ff90bfa
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)