# HG changeset patch # User Igor Sysoev # Date 1222789142 0 # Node ID 33556140681a92184274f325c56813a89ce7301c # Parent 920be89a3d2d7c1d70d9dce993fff251ff619162 *) ngx_http_upstream_test_next() *) add proxy_next_upstream http_502 and http_504 *) fix http_503 diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -147,7 +147,9 @@ static ngx_conf_bitmask_t ngx_http_prox { 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_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 }, { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, { ngx_null_string, 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 @@ -22,6 +22,8 @@ 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); @@ -284,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) { @@ -1174,53 +1185,16 @@ 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); + if (u->headers_in.status_n >= NGX_HTTP_BAD_REQUEST) { + + if (r->subrequest_in_memory) { + u->buffer.last = u->buffer.pos; + } + + if (ngx_http_upstream_test_next(r, u) == NGX_OK) { return; } -#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); - return; - } - - if (u->conf->intercept_404) { - ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND); - return; - } - } - - - if (u->headers_in.status_n >= NGX_HTTP_BAD_REQUEST) { - if (ngx_http_upstream_intercept_errors(r, u) == NGX_OK) { return; } @@ -1380,6 +1354,49 @@ 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) { diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -20,13 +20,20 @@ #define NGX_HTTP_UPSTREAM_FT_TIMEOUT 0x00000004 #define NGX_HTTP_UPSTREAM_FT_INVALID_HEADER 0x00000008 #define NGX_HTTP_UPSTREAM_FT_HTTP_500 0x00000010 -#define NGX_HTTP_UPSTREAM_FT_HTTP_503 0x00000020 -#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 0x00000020 +#define NGX_HTTP_UPSTREAM_FT_HTTP_503 0x00000040 +#define NGX_HTTP_UPSTREAM_FT_HTTP_504 0x00000080 +#define NGX_HTTP_UPSTREAM_FT_HTTP_404 0x00000100 +#define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK 0x00000200 +#define NGX_HTTP_UPSTREAM_FT_MAX_WAITING 0x00000400 #define NGX_HTTP_UPSTREAM_FT_NOLIVE 0x40000000 #define NGX_HTTP_UPSTREAM_FT_OFF 0x80000000 +#define NGX_HTTP_UPSTREAM_FT_STATUS (NGX_HTTP_UPSTREAM_FT_HTTP_500 \ + |NGX_HTTP_UPSTREAM_FT_HTTP_502 \ + |NGX_HTTP_UPSTREAM_FT_HTTP_503 \ + |NGX_HTTP_UPSTREAM_FT_HTTP_504 \ + |NGX_HTTP_UPSTREAM_FT_HTTP_404) #define NGX_HTTP_UPSTREAM_INVALID_HEADER 40 @@ -267,6 +274,12 @@ struct ngx_http_upstream_s { }; +typedef struct { + ngx_uint_t status; + ngx_uint_t mask; +} ngx_http_upstream_next_t; + + ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);