# HG changeset patch # User Igor Sysoev # Date 1232312400 -10800 # Node ID ce4f9ff90bfa58834c5b0db35395fd980c8c4aa0 # Parent 5da91f7cde939290dccf2e5bc0078e7ee322642f 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. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,10 +1,30 @@ +Changes with nginx 0.7.31 19 Jan 2009 + + *) 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. + + Changes with nginx 0.7.30 24 Dec 2008 *) Bugfix: a segmentation fault occurred in worker process, if - variables were used in the "fastcgi_pass" and "proxy_pass" - directives and host name must be resolved; the bug had appeared in - 0.7.29. + variables were used in the "fastcgi_pass" or "proxy_pass" directives + and host name must be resolved; the bug had appeared in 0.7.29. Changes with nginx 0.7.29 24 Dec 2008 diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,8 +1,29 @@ +Изменения в nginx 0.7.31 19.01.2009 + + *) Изменение: теперь директива try_files проверяет только файлы, + игнорируя каталоги. + + *) Добавление: директива fastcgi_split_path_info. + + *) Исправления в поддержке строки "Expect" в заголовке запроса. + + *) Исправления в гео-диапазонах. + + *) Исправление: при отсутствии ответа ngx_http_memcached_module + возвращал в теле ответа строку "END" вместо 404-ой страницы по + умолчанию; ошибка появилась в 0.7.18. + Спасибо Максиму Дунину. + + *) Исправление: при проксировании SMPT nginx выдавал сообщение + "250 2.0.0 OK" вместо "235 2.0.0 OK"; ошибка появилась в 0.7.22. + Спасибо Максиму Дунину. + + Изменения в nginx 0.7.30 24.12.2008 *) Исправление: в рабочем процессе происходил segmentation fault, если - в директивах fastcgi_pass и proxy_pass использовались переменные и + в директивах fastcgi_pass или proxy_pass использовались переменные и имя хоста должно было резолвиться; ошибка появилась в 0.7.29. diff --git a/LICENSE b/LICENSE --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2008 Igor Sysoev + * Copyright (C) 2002-2009 Igor Sysoev * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -21,5 +21,4 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * */ diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VERSION "0.7.30" +#define NGINX_VERSION "0.7.31" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -394,10 +394,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) cycle->log = cycle->new_log; pool->log = cycle->new_log; - if (cycle->log->log_level == 0) { - cycle->log->log_level = NGX_LOG_ERR; - } - /* create shared memory */ diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c --- a/src/core/ngx_log.c +++ b/src/core/ngx_log.c @@ -302,7 +302,10 @@ ngx_set_error_log_levels(ngx_conf_t *cf, } } - if (log->log_level == NGX_LOG_DEBUG) { + if (log->log_level == 0) { + log->log_level = NGX_LOG_ERR; + + } else if (log->log_level == NGX_LOG_DEBUG) { log->log_level = NGX_LOG_DEBUG_ALL; } diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c --- a/src/core/ngx_slab.c +++ b/src/core/ngx_slab.c @@ -685,7 +685,7 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *po } ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, NGX_ENOMEM, - "ngx_slab_alloc(): failed"); + "ngx_slab_alloc(): failed"); return NULL; } diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -22,6 +22,11 @@ typedef struct { ngx_array_t *fastcgi_lengths; ngx_array_t *fastcgi_values; + +#if (NGX_PCRE) + ngx_regex_t *split_regex; + ngx_str_t split_name; +#endif } ngx_http_fastcgi_loc_conf_t; @@ -56,6 +61,9 @@ typedef struct { ngx_uint_t fastcgi_stdout; /* unsigned :1 */ ngx_array_t *split_parts; + + ngx_str_t script_name; + ngx_str_t path_info; } ngx_http_fastcgi_ctx_t; @@ -125,9 +133,15 @@ static char *ngx_http_fastcgi_merge_loc_ void *parent, void *child); static ngx_int_t ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_fastcgi_path_info_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_fastcgi_split(ngx_http_request_t *r, + ngx_http_fastcgi_ctx_t *f, ngx_http_fastcgi_loc_conf_t *flcf); static char *ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_fastcgi_split_path_info(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); static char *ngx_http_fastcgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, @@ -171,6 +185,13 @@ static ngx_command_t ngx_http_fastcgi_c offsetof(ngx_http_fastcgi_loc_conf_t, index), NULL }, + { ngx_string("fastcgi_split_path_info"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_fastcgi_split_path_info, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + { ngx_string("fastcgi_store"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_http_fastcgi_store, @@ -390,8 +411,18 @@ static ngx_http_fastcgi_request_start_t }; -static ngx_str_t ngx_http_fastcgi_script_name = - ngx_string("fastcgi_script_name"); +static ngx_http_variable_t ngx_http_fastcgi_vars[] = { + + { ngx_string("fastcgi_script_name"), NULL, + ngx_http_fastcgi_script_name_variable, 0, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + + { ngx_string("fastcgi_path_info"), NULL, + ngx_http_fastcgi_path_info_variable, 0, + NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 }, + + { ngx_null_string, NULL, NULL, 0, 0, 0 } +}; static ngx_str_t ngx_http_fastcgi_hide_headers[] = { @@ -410,6 +441,7 @@ ngx_http_fastcgi_handler(ngx_http_reques { ngx_int_t rc; ngx_http_upstream_t *u; + ngx_http_fastcgi_ctx_t *f; ngx_http_fastcgi_loc_conf_t *flcf; if (r->subrequest_in_memory) { @@ -419,7 +451,12 @@ ngx_http_fastcgi_handler(ngx_http_reques return NGX_HTTP_INTERNAL_SERVER_ERROR; } - ngx_http_set_ctx(r, NULL, ngx_http_fastcgi_module); + f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t)); + if (f == NULL) { + return NGX_ERROR; + } + + ngx_http_set_ctx(r, f, ngx_http_fastcgi_module); u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); if (u == NULL) { @@ -933,15 +970,6 @@ ngx_http_fastcgi_process_header(ngx_http umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); - if (f == NULL) { - f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t)); - if (f == NULL) { - return NGX_ERROR; - } - - ngx_http_set_ctx(r, f, ngx_http_fastcgi_module); - } - u = r->upstream; for ( ;; ) { @@ -1666,16 +1694,18 @@ ngx_http_fastcgi_finalize_request(ngx_ht static ngx_int_t ngx_http_fastcgi_add_variables(ngx_conf_t *cf) { - ngx_http_variable_t *var; - - var = ngx_http_add_variable(cf, &ngx_http_fastcgi_script_name, - NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE); - if (var == NULL) { - return NGX_ERROR; + ngx_http_variable_t *var, *v; + + for (v = ngx_http_fastcgi_vars; v->name.len; v++) { + var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = v->get_handler; + var->data = v->data; } - var->get_handler = ngx_http_fastcgi_script_name_variable; - return NGX_OK; } @@ -1933,6 +1963,13 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf conf->fastcgi_values = prev->fastcgi_values; } +#if (NGX_PCRE) + if (conf->split_regex == NULL) { + conf->split_regex = prev->split_regex; + conf->split_name = prev->split_name; + } +#endif + if (conf->params_source == NULL) { conf->flushes = prev->flushes; conf->params_len = prev->params_len; @@ -2071,45 +2108,117 @@ ngx_http_fastcgi_script_name_variable(ng ngx_http_variable_value_t *v, uintptr_t data) { u_char *p; + ngx_http_fastcgi_ctx_t *f; ngx_http_fastcgi_loc_conf_t *flcf; - if (r->uri.len) { + f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); + flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); + + if (ngx_http_fastcgi_split(r, f, flcf) != NGX_OK) { + return NGX_ERROR; + } + + if (f->script_name.len == 0 + || f->script_name.data[f->script_name.len - 1] != '/') + { + v->len = f->script_name.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; - - flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); - - if (r->uri.data[r->uri.len - 1] != '/') { - v->len = r->uri.len; - v->data = r->uri.data; - return NGX_OK; - } - - v->len = r->uri.len + flcf->index.len; - - v->data = ngx_pnalloc(r->pool, v->len); - if (v->data == NULL) { - return NGX_ERROR; - } - - p = ngx_copy(v->data, r->uri.data, r->uri.len); - ngx_memcpy(p, flcf->index.data, flcf->index.len); - - } else { - v->len = 0; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->data = NULL; + v->data = f->script_name.data; return NGX_OK; } + v->len = f->script_name.len + flcf->index.len; + + v->data = ngx_pnalloc(r->pool, v->len); + if (v->data == NULL) { + return NGX_ERROR; + } + + p = ngx_copy(v->data, f->script_name.data, f->script_name.len); + ngx_memcpy(p, flcf->index.data, flcf->index.len); + return NGX_OK; } +static ngx_int_t +ngx_http_fastcgi_path_info_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_http_fastcgi_ctx_t *f; + ngx_http_fastcgi_loc_conf_t *flcf; + + f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); + flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); + + if (ngx_http_fastcgi_split(r, f, flcf) != NGX_OK) { + return NGX_ERROR; + } + + v->len = f->path_info.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = f->path_info.data; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_fastcgi_split(ngx_http_request_t *r, ngx_http_fastcgi_ctx_t *f, + ngx_http_fastcgi_loc_conf_t *flcf) +{ +#if (NGX_PCRE) + ngx_int_t n; + int captures[(1 + 2) * 3]; + + if (f->script_name.len) { + return NGX_OK; + } + + if (flcf->split_regex == NULL) { + f->script_name = r->uri; + return NGX_OK; + } + + n = ngx_regex_exec(flcf->split_regex, &r->uri, captures, (1 + 2) * 3); + + if (n == NGX_REGEX_NO_MATCHED) { + f->script_name = r->uri; + return NGX_OK; + } + + if (n < 0) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"", + n, &r->uri, &flcf->split_name); + return NGX_ERROR; + } + + /* match */ + + f->script_name.len = captures[3] - captures[2]; + f->script_name.data = r->uri.data; + + f->path_info.len = captures[5] - captures[4]; + f->path_info.data = r->uri.data + f->script_name.len; + + return NGX_OK; + +#else + + f->script_name = r->uri; + + return NGX_OK; + +#endif +} + + static char * ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { @@ -2172,6 +2281,57 @@ ngx_http_fastcgi_pass(ngx_conf_t *cf, ng static char * +ngx_http_fastcgi_split_path_info(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ +#if (NGX_PCRE) + ngx_http_fastcgi_loc_conf_t *flcf = conf; + + ngx_int_t n; + ngx_str_t *value, err; + u_char errstr[NGX_MAX_CONF_ERRSTR]; + + value = cf->args->elts; + + flcf->split_name = value[1]; + + err.len = NGX_MAX_CONF_ERRSTR; + err.data = errstr; + + flcf->split_regex = ngx_regex_compile(&value[1], 0, cf->pool, &err); + + if (flcf->split_regex == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); + return NGX_CONF_ERROR; + } + + n = ngx_regex_capture_count(flcf->split_regex); + + if (n < 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + ngx_regex_capture_count_n " failed for " + "pattern \"%V\"", &value[1]); + return NGX_CONF_ERROR; + } + + if (n != 2) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "pattern \"%V\" must have 2 captures", &value[1]); + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; + +#else + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"%V\" requires PCRE library", &cmd->name); + return NGX_CONF_ERROR; + +#endif +} + + +static char * ngx_http_fastcgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_fastcgi_loc_conf_t *flcf = conf; diff --git a/src/http/modules/ngx_http_flv_module.c b/src/http/modules/ngx_http_flv_module.c --- a/src/http/modules/ngx_http_flv_module.c +++ b/src/http/modules/ngx_http_flv_module.c @@ -160,7 +160,7 @@ ngx_http_flv_handler(ngx_http_request_t return NGX_DECLINED; } - r->root_tested = 1; + r->root_tested = !r->error_page; start = 0; len = of.size; diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c --- a/src/http/modules/ngx_http_geo_module.c +++ b/src/http/modules/ngx_http_geo_module.c @@ -518,10 +518,15 @@ ngx_http_geo_add_range(ngx_conf_t *cf, n ngx_array_t *a; ngx_http_geo_range_t *range; - for (n = start; n < end; n += 0x10000) { + for (n = start; n <= end; n += 0x10000) { h = n >> 16; - s = n & 0xffff; + + if (n == start) { + s = n & 0xffff; + } else { + s = 0; + } if ((n | 0xffff) > end) { e = end & 0xffff; @@ -567,7 +572,9 @@ ngx_http_geo_add_range(ngx_conf_t *cf, n ngx_memcpy(&range[i + 2], &range[i + 1], (a->nelts - 2 - i) * sizeof(ngx_http_geo_range_t)); - range = &range[i + 1]; + range[i + 1].start = (u_short) s; + range[i + 1].end = (u_short) e; + range[i + 1].value = ctx->value; goto next; } @@ -578,11 +585,101 @@ ngx_http_geo_add_range(ngx_conf_t *cf, n ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate range \"%V\", value: \"%v\", old value: \"%v\"", ctx->net, ctx->value, range[i].value); - continue; + + range[i].value = ctx->value; + + goto next; + } + + if (s > (ngx_uint_t) range[i].start + && e < (ngx_uint_t) range[i].end) + { + /* split the range and insert the new one */ + + range = ngx_array_push(a); + if (range == NULL) { + return NGX_CONF_ERROR; + } + + range = ngx_array_push(a); + if (range == NULL) { + return NGX_CONF_ERROR; + } + + range = a->elts; + + ngx_memcpy(&range[i + 3], &range[i + 1], + (a->nelts - 3 - i) * sizeof(ngx_http_geo_range_t)); + + range[i + 2].start = (u_short) (e + 1); + range[i + 2].end = range[i].end; + range[i + 2].value = range[i].value; + + range[i + 1].start = (u_short) s; + range[i + 1].end = (u_short) e; + range[i + 1].value = ctx->value; + + range[i].end = (u_short) (s - 1); + + goto next; } + if (s == (ngx_uint_t) range[i].start + && e < (ngx_uint_t) range[i].end) + { + /* shift the range start and insert the new range */ + + range = ngx_array_push(a); + if (range == NULL) { + return NGX_CONF_ERROR; + } + + range = a->elts; + + ngx_memcpy(&range[i + 2], &range[i + 1], + (a->nelts - 2 - i) * sizeof(ngx_http_geo_range_t)); + + range[i + 1].start = (u_short) (e + 1); + + range[i].start = (u_short) s; + range[i].end = (u_short) e; + range[i].value = ctx->value; + + goto next; + } + + if (s > (ngx_uint_t) range[i].start + && e == (ngx_uint_t) range[i].end) + { + /* shift the range end and insert the new range */ + + range = ngx_array_push(a); + if (range == NULL) { + return NGX_CONF_ERROR; + } + + range = a->elts; + + ngx_memcpy(&range[i + 2], &range[i + 1], + (a->nelts - 2 - i) * sizeof(ngx_http_geo_range_t)); + + range[i + 1].start = (u_short) s; + range[i + 1].end = (u_short) e; + range[i + 1].value = ctx->value; + + range[i].end = (u_short) (s - 1); + + goto next; + } + + s = (ngx_uint_t) range[i].start; + e = (ngx_uint_t) range[i].end; + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "overlapped range \"%V\"", ctx->net); + "range \"%V\" overlaps \"%d.%d.%d.%d-%d.%d.%d.%d\"", + ctx->net, + h >> 8, h & 0xff, s >> 8, s & 0xff, + h >> 8, h & 0xff, e >> 8, e & 0xff); return NGX_CONF_ERROR; } @@ -594,11 +691,13 @@ ngx_http_geo_add_range(ngx_conf_t *cf, n return NGX_CONF_ERROR; } - next: - range->start = (u_short) s; range->end = (u_short) e; range->value = ctx->value; + + next: + + continue; } return NGX_CONF_OK; @@ -616,10 +715,15 @@ ngx_http_geo_delete_range(ngx_conf_t *cf warn = 0; - for (n = start; n < end; n += 0x10000) { + for (n = start; n <= end; n += 0x10000) { h = n >> 16; - s = n & 0xffff; + + if (n == start) { + s = n & 0xffff; + } else { + s = 0; + } if ((n | 0xffff) > end) { e = end & 0xffff; @@ -643,6 +747,9 @@ ngx_http_geo_delete_range(ngx_conf_t *cf { ngx_memcpy(&range[i], &range[i + 1], (a->nelts - 1 - i) * sizeof(ngx_http_geo_range_t)); + + a->nelts--; + break; } diff --git a/src/http/modules/ngx_http_gzip_static_module.c b/src/http/modules/ngx_http_gzip_static_module.c --- a/src/http/modules/ngx_http_gzip_static_module.c +++ b/src/http/modules/ngx_http_gzip_static_module.c @@ -176,7 +176,7 @@ ngx_http_gzip_static_handler(ngx_http_re #endif - r->root_tested = 1; + r->root_tested = !r->error_page; rc = ngx_http_discard_request_body(r); diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -135,7 +135,7 @@ ngx_http_static_handler(ngx_http_request return rc; } - r->root_tested = 1; + r->root_tested = !r->error_page; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd); diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -47,7 +47,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.7.30'; +our $VERSION = '0.7.31'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -23,7 +23,6 @@ typedef struct { static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r); static ngx_int_t ngx_http_core_find_static_location(ngx_http_request_t *r, ngx_http_location_tree_node_t *node); -static ngx_int_t ngx_http_core_send_continue(ngx_http_request_t *r); static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf); static void *ngx_http_core_create_main_conf(ngx_conf_t *cf); @@ -818,7 +817,7 @@ ngx_http_core_find_config_phase(ngx_http { u_char *p; size_t len; - ngx_int_t rc, expect; + ngx_int_t rc; ngx_http_core_loc_conf_t *clcf; r->content_handler = NULL; @@ -862,15 +861,6 @@ ngx_http_core_find_config_phase(ngx_http return NGX_OK; } - if (r->headers_in.expect && r->http_version > NGX_HTTP_VERSION_10) { - expect = ngx_http_core_send_continue(r); - - if (expect != NGX_OK) { - ngx_http_finalize_request(r, expect); - return NGX_OK; - } - } - if (rc == NGX_DONE) { r->headers_out.location = ngx_list_push(&r->headers_out.headers); if (r->headers_out.location == NULL) { @@ -1182,6 +1172,10 @@ ngx_http_core_try_files_phase(ngx_http_r continue; } + if (!of.is_file) { + continue; + } + path.len -= root; path.data += root; @@ -1490,45 +1484,6 @@ ngx_http_core_find_static_location(ngx_h } -static ngx_int_t -ngx_http_core_send_continue(ngx_http_request_t *r) -{ - ngx_int_t n; - ngx_str_t *expect; - - if (r->expect_tested) { - return NGX_OK; - } - - r->expect_tested = 1; - - expect = &r->headers_in.expect->value; - - if (expect->len != sizeof("100-continue") - 1 - || ngx_strncasecmp(expect->data, (u_char *) "100-continue", - sizeof("100-continue") - 1) - != 0) - { - return NGX_OK; - } - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "send 100 Continue"); - - n = r->connection->send(r->connection, - (u_char *) "HTTP/1.1 100 Continue" CRLF CRLF, - sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1); - - if (n == sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1) { - return NGX_OK; - } - - /* we assume that such small packet should be send successfully */ - - return NGX_HTTP_INTERNAL_SERVER_ERROR; -} - - void * ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash) { @@ -2125,6 +2080,7 @@ ngx_http_subrequest(ngx_http_request_t * sr->internal = 1; sr->discard_body = r->discard_body; + sr->expect_tested = 1; sr->main_filter_need_in_memory = r->main_filter_need_in_memory; sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1; diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -15,6 +15,7 @@ static ngx_int_t ngx_http_write_request_ ngx_chain_t *body); static void ngx_http_read_discarded_request_body_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r); +static ngx_int_t ngx_http_test_expect(ngx_http_request_t *r); /* @@ -41,6 +42,10 @@ ngx_http_read_client_request_body(ngx_ht return NGX_OK; } + if (ngx_http_test_expect(r) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); if (rb == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -433,6 +438,10 @@ ngx_http_discard_request_body(ngx_http_r return NGX_OK; } + if (ngx_http_test_expect(r) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + rev = r->connection->read; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body"); @@ -581,3 +590,45 @@ ngx_http_read_discarded_request_body(ngx return NGX_AGAIN; } + + +static ngx_int_t +ngx_http_test_expect(ngx_http_request_t *r) +{ + ngx_int_t n; + ngx_str_t *expect; + + if (r->expect_tested + || r->headers_in.expect == NULL + || r->http_version < NGX_HTTP_VERSION_11) + { + return NGX_OK; + } + + r->expect_tested = 1; + + expect = &r->headers_in.expect->value; + + if (expect->len != sizeof("100-continue") - 1 + || ngx_strncasecmp(expect->data, (u_char *) "100-continue", + sizeof("100-continue") - 1) + != 0) + { + return NGX_OK; + } + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "send 100 Continue"); + + n = r->connection->send(r->connection, + (u_char *) "HTTP/1.1 100 Continue" CRLF CRLF, + sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1); + + if (n == sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1) { + return NGX_OK; + } + + /* we assume that such small packet should be send successfully */ + + return NGX_ERROR; +} diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -379,6 +379,8 @@ ngx_http_special_response_handler(ngx_ht } } + r->expect_tested = 1; + if (ngx_http_discard_request_body(r) != NGX_OK) { error = NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -431,11 +433,18 @@ static ngx_int_t ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page) { u_char ch, *p, *last; + ngx_int_t overwrite; ngx_str_t *uri, *args, u, a; ngx_table_elt_t *location; ngx_http_core_loc_conf_t *clcf; - r->err_status = err_page->overwrite; + overwrite = err_page->overwrite; + + if (overwrite && overwrite != NGX_HTTP_OK) { + r->expect_tested = 1; + } + + r->err_status = overwrite; r->zero_in_uri = 0; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -1441,11 +1441,6 @@ ngx_http_upstream_test_next(ngx_http_req return NGX_OK; } - if (status == NGX_HTTP_NOT_FOUND && u->conf->intercept_404) { - ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND); - return NGX_OK; - } - #if (NGX_HTTP_CACHE) if (u->peer.tries == 0 && u->stale && (u->conf->use_stale & un->mask)) { @@ -1471,6 +1466,13 @@ ngx_http_upstream_intercept_errors(ngx_h ngx_http_err_page_t *err_page; ngx_http_core_loc_conf_t *clcf; + status = u->headers_in.status_n; + + if (status == NGX_HTTP_NOT_FOUND && u->conf->intercept_404) { + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND); + return NGX_OK; + } + if (!u->conf->intercept_errors) { return NGX_DECLINED; } @@ -1481,8 +1483,6 @@ ngx_http_upstream_intercept_errors(ngx_h return NGX_DECLINED; } - status = u->headers_in.status_n; - err_page = clcf->error_pages->elts; for (i = 0; i < clcf->error_pages->nelts; i++) { @@ -2201,6 +2201,7 @@ ngx_http_upstream_process_upstream(ngx_h static void ngx_http_upstream_process_request(ngx_http_request_t *r) { + ngx_uint_t del; ngx_temp_file_t *tf; ngx_event_pipe_t *p; ngx_http_upstream_t *u; @@ -2212,20 +2213,25 @@ ngx_http_upstream_process_request(ngx_ht if (u->store) { + del = p->upstream_error; + tf = u->pipe->temp_file; - if (p->upstream_eof - && u->headers_in.status_n == NGX_HTTP_OK - && (u->headers_in.content_length_n == -1 - || (u->headers_in.content_length_n == tf->offset))) - { - ngx_http_upstream_store(r, u); - - } else if ((p->upstream_error - || (p->upstream_eof - && u->headers_in.status_n != NGX_HTTP_OK)) - && tf->file.fd != NGX_INVALID_FILE) - { + if (p->upstream_eof) { + + if (u->headers_in.status_n == NGX_HTTP_OK + && (u->headers_in.content_length_n == -1 + || (u->headers_in.content_length_n == tf->offset))) + { + ngx_http_upstream_store(r, u); + + } else { + del = 1; + } + } + + if (del && tf->file.fd != NGX_INVALID_FILE) { + if (ngx_delete_file(tf->file.name.data) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c --- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -104,7 +104,7 @@ ngx_module_t ngx_mail_proxy_module = { }; -static u_char smtp_ok[] = "250 2.0.0 OK" CRLF; +static u_char smtp_auth_ok[] = "235 2.0.0 OK" CRLF; void @@ -614,8 +614,8 @@ ngx_mail_proxy_smtp_handler(ngx_event_t b->pos = b->start; } else { - ngx_memcpy(b->start, smtp_ok, sizeof(smtp_ok) - 1); - b->last = b->start + sizeof(smtp_ok) - 1; + ngx_memcpy(b->start, smtp_auth_ok, sizeof(smtp_auth_ok) - 1); + b->last = b->start + sizeof(smtp_auth_ok) - 1; } s->connection->read->handler = ngx_mail_proxy_handler; diff --git a/src/os/unix/ngx_posix_init.c b/src/os/unix/ngx_posix_init.c --- a/src/os/unix/ngx_posix_init.c +++ b/src/os/unix/ngx_posix_init.c @@ -22,7 +22,7 @@ ngx_os_io_t ngx_os_io = { ngx_unix_recv, ngx_readv_chain, ngx_udp_unix_recv, - NULL, + ngx_unix_send, ngx_writev_chain, 0 };