>From e049fed661bad9beb8a40db3153f9042cb5836e1 Mon Sep 17 00:00:00 2001
From: Tomash Brechko <tomash.brechko@gmail.com>
Date: Sat, 19 Jul 2008 11:20:50 +0400
Subject: [PATCH] Enhance next upstream logic.

Fix 503, process 502, 504, 507 HTTP status codes.

Most of the code is by Maxim Dounin.
---
 server/src/http/modules/ngx_http_fastcgi_module.c |    3 +
 server/src/http/modules/ngx_http_proxy_module.c   |    3 +
 server/src/http/ngx_http_upstream.c               |   52 +++++++++++++++++++++
 server/src/http/ngx_http_upstream.h               |    3 +
 4 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/server/src/http/modules/ngx_http_fastcgi_module.c b/server/src/http/modules/ngx_http_fastcgi_module.c
index b975c06..525d535 100644
--- a/server/src/http/modules/ngx_http_fastcgi_module.c
+++ b/server/src/http/modules/ngx_http_fastcgi_module.c
@@ -144,7 +144,10 @@ static ngx_conf_bitmask_t  ngx_http_fastcgi_next_upstream_masks[] = {
     { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
     { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
     { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
+    { ngx_string("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502 },
     { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
+    { ngx_string("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504 },
+    { ngx_string("http_507"), NGX_HTTP_UPSTREAM_FT_HTTP_507 },
     { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
     { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
     { ngx_null_string, 0 }
diff --git a/server/src/http/modules/ngx_http_proxy_module.c b/server/src/http/modules/ngx_http_proxy_module.c
index 8a7f2ab..2b3f4a2 100644
--- a/server/src/http/modules/ngx_http_proxy_module.c
+++ b/server/src/http/modules/ngx_http_proxy_module.c
@@ -148,7 +148,10 @@ static ngx_conf_bitmask_t  ngx_http_proxy_next_upstream_masks[] = {
     { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
     { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
     { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
+    { ngx_string("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502 },
     { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
+    { ngx_string("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504 },
+    { ngx_string("http_507"), NGX_HTTP_UPSTREAM_FT_HTTP_507 },
     { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
     { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
     { ngx_null_string, 0 }
diff --git a/server/src/http/ngx_http_upstream.c b/server/src/http/ngx_http_upstream.c
index 27f27ae..7dd99ba 100644
--- a/server/src/http/ngx_http_upstream.c
+++ b/server/src/http/ngx_http_upstream.c
@@ -1213,6 +1213,45 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
         }
     }
 
+    if (u->headers_in.status_n == NGX_HTTP_BAD_GATEWAY) {
+
+        if (u->peer.tries > 1
+            && u->conf->next_upstream & NGX_HTTP_UPSTREAM_FT_HTTP_502)
+        {
+            ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_HTTP_502);
+            return;
+        }
+    }
+
+    if (u->headers_in.status_n == NGX_HTTP_SERVICE_UNAVAILABLE) {
+
+        if (u->peer.tries > 1
+            && u->conf->next_upstream & NGX_HTTP_UPSTREAM_FT_HTTP_503)
+        {
+            ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_HTTP_503);
+            return;
+        }
+    }
+
+    if (u->headers_in.status_n == NGX_HTTP_GATEWAY_TIME_OUT) {
+
+        if (u->peer.tries > 1
+            && u->conf->next_upstream & NGX_HTTP_UPSTREAM_FT_HTTP_504)
+        {
+            ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_HTTP_504);
+            return;
+        }
+    }
+
+    if (u->headers_in.status_n == NGX_HTTP_INSUFFICIENT_STORAGE) {
+
+        if (u->peer.tries > 1
+            && u->conf->next_upstream & NGX_HTTP_UPSTREAM_FT_HTTP_507)
+        {
+            ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_HTTP_507);
+            return;
+        }
+    }
 
     if (u->headers_in.status_n >= NGX_HTTP_BAD_REQUEST
         && u->conf->intercept_errors)
@@ -2239,6 +2278,7 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
     } else {
         switch(ft_type) {
 
+        case NGX_HTTP_UPSTREAM_FT_HTTP_504:
         case NGX_HTTP_UPSTREAM_FT_TIMEOUT:
             status = NGX_HTTP_GATEWAY_TIME_OUT;
             break;
@@ -2251,6 +2291,18 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
             status = NGX_HTTP_NOT_FOUND;
             break;
 
+        case NGX_HTTP_UPSTREAM_FT_HTTP_502:
+            status = NGX_HTTP_BAD_GATEWAY;
+            break;
+
+        case NGX_HTTP_UPSTREAM_FT_HTTP_503:
+            status = NGX_HTTP_SERVICE_UNAVAILABLE;
+            break;
+
+        case NGX_HTTP_UPSTREAM_FT_HTTP_507:
+            status = NGX_HTTP_INSUFFICIENT_STORAGE;
+            break;
+
         /*
          * NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING
          * never reach here
diff --git a/server/src/http/ngx_http_upstream.h b/server/src/http/ngx_http_upstream.h
index 2ed2797..6754d65 100644
--- a/server/src/http/ngx_http_upstream.h
+++ b/server/src/http/ngx_http_upstream.h
@@ -24,6 +24,9 @@
 #define NGX_HTTP_UPSTREAM_FT_HTTP_404        0x00000040
 #define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK       0x00000080
 #define NGX_HTTP_UPSTREAM_FT_MAX_WAITING     0x00000100
+#define NGX_HTTP_UPSTREAM_FT_HTTP_502        0x00000200
+#define NGX_HTTP_UPSTREAM_FT_HTTP_504        0x00000400
+#define NGX_HTTP_UPSTREAM_FT_HTTP_507        0x00000800
 #define NGX_HTTP_UPSTREAM_FT_NOLIVE          0x40000000
 #define NGX_HTTP_UPSTREAM_FT_OFF             0x80000000
 
-- 
1.5.5.1.116.ge4b9c

