changeset 228:9eebc1b2cdbb NGINX_0_3_61

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.
author Igor Sysoev <http://sysoev.ru>
date Mon, 28 Aug 2006 00:00:00 +0400
parents f554f17a0fb7
children 1965c8e23be7
files CHANGES CHANGES.ru src/core/nginx.h src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_request.h src/http/ngx_http_script.c src/http/ngx_http_special_response.c
diffstat 8 files changed, 155 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- 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 
--- 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
 
     *) Исправление: во время перенаправления ошибки рабочий процесс мог 
--- 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"
--- 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;
--- 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 */
 
--- 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;
--- 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 "?" */
 
--- 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[] =
+"<html><head><meta http-equiv=\"Refresh\" content=\"0; URL=";
+
+
+static u_char ngx_http_msie_refresh_tail[] =
+"\"></head><body></body></html>" CRLF;
+
+
 static char error_301_page[] =
 "<html>" CRLF
 "<head><title>301 Moved Permanently</title></head>" 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) {