# HG changeset patch # User Igor Sysoev # Date 1156708800 -14400 # Node ID 9eebc1b2cdbb1fa37cf2e26f54b97e666df63aa1 # Parent f554f17a0fb7196fe6f853195357ef8705692461 nginx 0.3.61 *) Change: now the "tcp_nodelay" directive is turned on by default. *) Feature: the "msie_refresh" directive. *) Feature: the "recursive_error_pages" directive. *) Bugfix: the "rewrite" directive returned incorrect redirect, if the redirect had the captured escaped symbols from original URI. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,14 @@ +Changes with nginx 0.3.61 28 Aug 2006 + + *) Feature: the "msie_refresh" directive. + + *) Feature: the "recursive_error_pages" directive. + + *) Bugfix: the "rewrite" directive returned incorrect redirect, if the + redirect had the captured escaped symbols from original URI. + + Changes with nginx 0.3.60 18 Aug 2006 *) Bugfix: a worker process may got caught in an endless loop while an diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,15 @@ +Изменения в nginx 0.3.61 28.08.2006 + + *) Добавление: директива msie_refresh. + + *) Добавление: директива recursive_error_pages. + + *) Исправление: директива rewrite возвращала неправильный редирект, + если редирект включал в себя выделенные закодированные символы из + оригинального URI. + + Изменения в nginx 0.3.60 18.08.2006 *) Исправление: во время перенаправления ошибки рабочий процесс мог 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_VER "nginx/0.3.60" +#define NGINX_VER "nginx/0.3.61" #define NGINX_VAR "NGINX" #define NGX_OLDPID_EXT ".oldbin" 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 @@ -381,6 +381,13 @@ static ngx_command_t ngx_http_core_comm offsetof(ngx_http_core_loc_conf_t, msie_padding), NULL }, + { ngx_string("msie_refresh"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, msie_refresh), + NULL }, + { ngx_string("log_not_found"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -388,6 +395,13 @@ static ngx_command_t ngx_http_core_comm offsetof(ngx_http_core_loc_conf_t, log_not_found), NULL }, + { ngx_string("recursive_error_pages"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, recursive_error_pages), + NULL }, + { ngx_string("error_page"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_2MORE, @@ -547,7 +561,8 @@ ngx_http_core_run_phases(ngx_http_reques if (r->uri_changes == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "rewrite or internal redirection cycle"); + "rewrite or internal redirection cycle " + "while processing \"%V\"", &r->uri); ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } @@ -1181,7 +1196,7 @@ ngx_http_subrequest(ngx_http_request_t * if (r->main->subrequests == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "subrequests cycle"); + "subrequests cycle while processing \"%V\"", uri); return NGX_ERROR; } @@ -1328,7 +1343,9 @@ ngx_http_internal_redirect(ngx_http_requ if (r->uri_changes == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "rewrite or internal redirection cycle"); + "rewrite or internal redirection cycle " + "while internal redirect to \"%V\"", uri); + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_DONE; } @@ -2052,7 +2069,9 @@ ngx_http_core_create_loc_conf(ngx_conf_t lcf->reset_timedout_connection = NGX_CONF_UNSET; lcf->port_in_redirect = NGX_CONF_UNSET; lcf->msie_padding = NGX_CONF_UNSET; + lcf->msie_refresh = NGX_CONF_UNSET; lcf->log_not_found = NGX_CONF_UNSET; + lcf->recursive_error_pages = NGX_CONF_UNSET; lcf->types_hash_max_size = NGX_CONF_UNSET_UINT; lcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT; @@ -2206,7 +2225,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t prev->client_body_in_file_only, 0); ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0); ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0); - ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 0); + ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1); ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000); ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0); @@ -2231,7 +2250,10 @@ ngx_http_core_merge_loc_conf(ngx_conf_t prev->reset_timedout_connection, 0); ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1); ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1); + ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0); ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1); + ngx_conf_merge_value(conf->recursive_error_pages, + prev->recursive_error_pages, 0); if (conf->open_files == NULL) { conf->open_files = prev->open_files; diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -241,7 +241,9 @@ struct ngx_http_core_loc_conf_s { ngx_flag_t reset_timedout_connection; /* reset_timedout_connection */ ngx_flag_t port_in_redirect; /* port_in_redirect */ ngx_flag_t msie_padding; /* msie_padding */ + ngx_flag_t msie_refresh; /* msie_refresh */ ngx_flag_t log_not_found; /* log_not_found */ + ngx_flag_t recursive_error_pages; /* recursive_error_pages */ ngx_array_t *error_pages; /* error_page */ diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -434,6 +434,7 @@ struct ngx_http_request_s { unsigned lingering_close:1; unsigned discard_body:1; unsigned internal:1; + unsigned error_page:1; unsigned post_action:1; unsigned request_complete:1; unsigned request_output:1; diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -687,9 +687,11 @@ ngx_http_script_regex_start_code(ngx_htt ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); le.ip = code->lengths->elts; + le.line = e->line; le.request = r; le.captures = e->captures; le.ncaptures = e->ncaptures; + le.quote = code->redirect; len = 1; /* reserve 1 byte for possible "?" */ 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 @@ -27,6 +27,14 @@ static u_char ngx_http_msie_stub[] = ; +static u_char ngx_http_msie_refresh_head[] = +"" CRLF; + + static char error_301_page[] = "" CRLF "301 Moved Permanently" CRLF @@ -294,9 +302,11 @@ static ngx_str_t error_pages[] = { ngx_int_t ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error) { + u_char *p; + size_t msie_refresh; ngx_int_t rc; ngx_buf_t *b; - ngx_str_t *uri; + ngx_str_t *uri, *location; ngx_uint_t i, err, msie_padding; ngx_chain_t *out, *cl; ngx_http_err_page_t *err_page; @@ -311,7 +321,6 @@ ngx_http_special_response_handler(ngx_ht error = NGX_HTTP_INTERNAL_SERVER_ERROR; } - r->headers_out.status = error; r->err_status = error; if (r->keepalive != 0) { @@ -341,7 +350,11 @@ ngx_http_special_response_handler(ngx_ht clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (r->uri_changes && clcf->error_pages) { + if (!r->error_page && clcf->error_pages) { + + if (clcf->recursive_error_pages == 0) { + r->error_page = 1; + } err_page = clcf->error_pages->elts; @@ -415,7 +428,7 @@ ngx_http_special_response_handler(ngx_ht case NGX_HTTP_TO_HTTPS: case NGX_HTTPS_CERT_ERROR: case NGX_HTTPS_NO_CERT: - r->headers_out.status = NGX_HTTP_BAD_REQUEST; + r->err_status = NGX_HTTP_BAD_REQUEST; error = NGX_HTTP_BAD_REQUEST; break; } @@ -449,6 +462,26 @@ ngx_http_special_response_handler(ngx_ht r->headers_out.content_length = NULL; } + msie_refresh = 0; + location = NULL; + + if (clcf->msie_refresh + && r->headers_in.msie + && (error == NGX_HTTP_MOVED_PERMANENTLY + || error == NGX_HTTP_MOVED_TEMPORARILY)) + { + location = &r->headers_out.location->value; + msie_refresh = sizeof(ngx_http_msie_refresh_head) - 1 + + location->len + + sizeof(ngx_http_msie_refresh_tail) - 1; + + r->err_status = NGX_HTTP_OK; + r->headers_out.content_type_len = sizeof("text/html") - 1; + r->headers_out.content_length_n = msie_refresh; + r->headers_out.location->hash = 0; + r->headers_out.location = NULL; + } + ngx_http_clear_accept_ranges(r); ngx_http_clear_last_modified(r); @@ -458,55 +491,39 @@ ngx_http_special_response_handler(ngx_ht return rc; } - if (error_pages[err].len == 0) { - return NGX_OK; - } - - b = ngx_calloc_buf(r->pool); - if (b == NULL) { - return NGX_ERROR; - } - - b->memory = 1; - b->pos = error_pages[err].data; - b->last = error_pages[err].data + error_pages[err].len; - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NGX_ERROR; - } + if (msie_refresh == 0) { - cl->buf = b; - out = cl; - - - b = ngx_calloc_buf(r->pool); - if (b == NULL) { - return NGX_ERROR; - } + if (error_pages[err].len == 0) { + return NGX_OK; + } - b->memory = 1; - b->pos = error_tail; - b->last = error_tail + sizeof(error_tail) - 1; - - cl->next = ngx_alloc_chain_link(r->pool); - if (cl->next == NULL) { - return NGX_ERROR; - } - - cl = cl->next; - cl->buf = b; - - if (msie_padding) { b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } b->memory = 1; - b->pos = ngx_http_msie_stub; - b->last = ngx_http_msie_stub + sizeof(ngx_http_msie_stub) - 1; + b->pos = error_pages[err].data; + b->last = error_pages[err].data + error_pages[err].len; + + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NGX_ERROR; + } + + cl->buf = b; + out = cl; + + + b = ngx_calloc_buf(r->pool); + if (b == NULL) { + return NGX_ERROR; + } + + b->memory = 1; + b->pos = error_tail; + b->last = error_tail + sizeof(error_tail) - 1; cl->next = ngx_alloc_chain_link(r->pool); if (cl->next == NULL) { @@ -515,6 +532,47 @@ ngx_http_special_response_handler(ngx_ht cl = cl->next; cl->buf = b; + + if (msie_padding) { + b = ngx_calloc_buf(r->pool); + if (b == NULL) { + return NGX_ERROR; + } + + b->memory = 1; + b->pos = ngx_http_msie_stub; + b->last = ngx_http_msie_stub + sizeof(ngx_http_msie_stub) - 1; + + cl->next = ngx_alloc_chain_link(r->pool); + if (cl->next == NULL) { + return NGX_ERROR; + } + + cl = cl->next; + cl->buf = b; + } + + } else { + b = ngx_create_temp_buf(r->pool, msie_refresh); + if (b == NULL) { + return NGX_ERROR; + } + + p = ngx_cpymem(b->pos, ngx_http_msie_refresh_head, + sizeof(ngx_http_msie_refresh_head) - 1); + + p = ngx_cpymem(p, location->data, location->len); + + b->last = ngx_cpymem(p, ngx_http_msie_refresh_tail, + sizeof(ngx_http_msie_refresh_tail) - 1); + + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NGX_ERROR; + } + + cl->buf = b; + out = cl; } if (r == r->main) {