diff src/http/ngx_http_upstream.c @ 412:b246022ef454 NGINX_0_7_18

nginx 0.7.18 *) Change: the "underscores_in_headers" directive; now nginx does not allows underscores in a client request header line names. *) Feature: the ngx_http_secure_link_module. *) Feature: the "real_ip_header" directive supports any header. *) Feature: the "log_subrequest" directive. *) Feature: the $realpath_root variable. *) Feature: the "http_502" and "http_504" parameters of the "proxy_next_upstream" directive. *) Bugfix: the "http_503" parameter of the "proxy_next_upstream" or "fastcgi_next_upstream" directives did not work. *) Bugfix: nginx might send a "Transfer-Encoding: chunked" heaer line for HEAD requests. *) Bugfix: now accept threshold depends on worker_connections.
author Igor Sysoev <http://sysoev.ru>
date Mon, 13 Oct 2008 00:00:00 +0400
parents a8e3f1441eec
children b4f69f2ef02c
line wrap: on
line diff
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -22,6 +22,10 @@ static void ngx_http_upstream_send_reque
     ngx_http_upstream_t *u);
 static void ngx_http_upstream_send_request_handler(ngx_event_t *wev);
 static void ngx_http_upstream_process_header(ngx_event_t *rev);
+static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
+    ngx_http_upstream_t *u);
+static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
+    ngx_http_upstream_t *u);
 static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c);
 static void ngx_http_upstream_process_body_in_memory(ngx_event_t *rev);
 static void ngx_http_upstream_send_response(ngx_http_request_t *r,
@@ -282,6 +286,15 @@ static ngx_http_variable_t  ngx_http_ups
 };
 
 
+static ngx_http_upstream_next_t  ngx_http_upstream_next_errors[] = {
+    { 500, NGX_HTTP_UPSTREAM_FT_HTTP_500 },
+    { 502, NGX_HTTP_UPSTREAM_FT_HTTP_502 },
+    { 503, NGX_HTTP_UPSTREAM_FT_HTTP_503 },
+    { 504, NGX_HTTP_UPSTREAM_FT_HTTP_504 },
+    { 404, NGX_HTTP_UPSTREAM_FT_HTTP_404 },
+    { 0, 0 }
+};
+
 void
 ngx_http_upstream_init(ngx_http_request_t *r)
 {
@@ -1047,8 +1060,6 @@ ngx_http_upstream_process_header(ngx_eve
     ngx_connection_t               *c;
     ngx_http_request_t             *r;
     ngx_http_upstream_t            *u;
-    ngx_http_err_page_t            *err_page;
-    ngx_http_core_loc_conf_t       *clcf;
     ngx_http_upstream_header_t     *hh;
     ngx_http_upstream_main_conf_t  *umcf;
 
@@ -1174,85 +1185,21 @@ ngx_http_upstream_process_header(ngx_eve
 
     /* rc == NGX_OK */
 
-    if (u->headers_in.status_n >= NGX_HTTP_BAD_REQUEST
-        && r->subrequest_in_memory)
-    {
-        u->buffer.last = u->buffer.pos;
-    }
-
-    if (u->headers_in.status_n == NGX_HTTP_INTERNAL_SERVER_ERROR) {
-
-        if (u->peer.tries > 1
-            && (u->conf->next_upstream & NGX_HTTP_UPSTREAM_FT_HTTP_500))
-        {
-            ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_HTTP_500);
-            return;
+    if (u->headers_in.status_n >= NGX_HTTP_BAD_REQUEST) {
+
+        if (r->subrequest_in_memory) {
+            u->buffer.last = u->buffer.pos;
         }
 
-#if (NGX_HTTP_CACHE)
-
-        if (u->peer.tries == 0
-            && u->stale
-            && (u->conf->use_stale & NGX_HTTP_UPSTREAM_FT_HTTP_500))
-        {
-            ngx_http_upstream_finalize_request(r, u,
-                                              ngx_http_send_cached_response(r));
-            return;
-        }
-
-#endif
-    }
-
-    if (u->headers_in.status_n == NGX_HTTP_NOT_FOUND) {
-
-        if (u->peer.tries > 1
-            && u->conf->next_upstream & NGX_HTTP_UPSTREAM_FT_HTTP_404)
-        {
-            ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_HTTP_404);
+        if (ngx_http_upstream_test_next(r, u) == NGX_OK) {
             return;
         }
 
-        if (u->conf->intercept_404) {
-            ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND);
+        if (ngx_http_upstream_intercept_errors(r, u) == NGX_OK) {
             return;
         }
     }
 
-
-    if (u->headers_in.status_n >= NGX_HTTP_BAD_REQUEST
-        && u->conf->intercept_errors)
-    {
-        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
-        if (clcf->error_pages) {
-
-            err_page = clcf->error_pages->elts;
-            for (i = 0; i < clcf->error_pages->nelts; i++) {
-                if (err_page[i].status == (ngx_int_t) u->headers_in.status_n) {
-
-                    if (u->headers_in.status_n == NGX_HTTP_UNAUTHORIZED) {
-
-                        r->headers_out.www_authenticate =
-                                        ngx_list_push(&r->headers_out.headers);
-
-                        if (r->headers_out.www_authenticate == NULL) {
-                            ngx_http_upstream_finalize_request(r, u,
-                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
-                            return;
-                        }
-
-                        *r->headers_out.www_authenticate =
-                                               *u->headers_in.www_authenticate;
-                    }
-
-                    ngx_http_upstream_finalize_request(r, u,
-                                                       u->headers_in.status_n);
-                    return;
-                }
-            }
-        }
-    }
-
     umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
 
     if (u->headers_in.x_accel_redirect) {
@@ -1407,6 +1354,101 @@ ngx_http_upstream_process_header(ngx_eve
 
 
 static ngx_int_t
+ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
+{
+    ngx_uint_t                 status;
+    ngx_http_upstream_next_t  *un;
+
+    if (!(u->conf->next_upstream & NGX_HTTP_UPSTREAM_FT_STATUS)) {
+        return NGX_DECLINED;
+    }
+
+    status = u->headers_in.status_n;
+
+    for (un = ngx_http_upstream_next_errors; un->status; un++) {
+
+        if (status != un->status) {
+            continue;
+        }
+
+        if (u->peer.tries > 1 && (u->conf->next_upstream & un->mask)) {
+            ngx_http_upstream_next(r, u, un->mask);
+            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)) {
+            ngx_http_upstream_finalize_request(r, u,
+                                              ngx_http_send_cached_response(r));
+            return NGX_OK;
+        }
+
+#endif
+    }
+
+    return NGX_DECLINED;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
+    ngx_http_upstream_t *u)
+{
+    ngx_int_t                  status;
+    ngx_uint_t                 i;
+    ngx_table_elt_t           *h;
+    ngx_http_err_page_t       *err_page;
+    ngx_http_core_loc_conf_t  *clcf;
+
+    if (!u->conf->intercept_errors) {
+        return NGX_DECLINED;
+    }
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    if (clcf->error_pages == NULL) {
+        return NGX_DECLINED;
+    }
+
+    status = u->headers_in.status_n;
+
+    err_page = clcf->error_pages->elts;
+    for (i = 0; i < clcf->error_pages->nelts; i++) {
+
+        if (err_page[i].status == status) {
+
+            if (status == NGX_HTTP_UNAUTHORIZED) {
+
+                h = ngx_list_push(&r->headers_out.headers);
+
+                if (h == NULL) {
+                    ngx_http_upstream_finalize_request(r, u,
+                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
+                    return NGX_OK;
+                }
+
+                *h = *u->headers_in.www_authenticate;
+
+                r->headers_out.www_authenticate = h;
+            }
+
+            ngx_http_upstream_finalize_request(r, u, status);
+
+            return NGX_OK;
+        }
+    }
+
+    return NGX_DECLINED;
+}
+
+
+static ngx_int_t
 ngx_http_upstream_test_connect(ngx_connection_t *c)
 {
     int        err;