From 45ba5539372fd6890c2a223ab543621c4e00aeac Mon Sep 17 00:00:00 2001
From: "amirhossein.vz" <hosseinvadi7777@gmail.com>
Date: Sat, 9 Mar 2019 15:27:03 +0330
Subject: [PATCH] sudpport variable poxy next upstream directive

---
 src/http/modules/ngx_http_proxy_module.c | 59 +++++++++++---------
 src/http/ngx_http_upstream.c             | 70 ++++++++++++++++++++++++
 src/http/ngx_http_upstream.h             |  1 +
 3 files changed, 103 insertions(+), 27 deletions(-)
 mode change 100644 => 100755 src/http/modules/ngx_http_proxy_module.c
 mode change 100644 => 100755 src/http/ngx_http_upstream.c
 mode change 100644 => 100755 src/http/ngx_http_upstream.h

diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
old mode 100644
new mode 100755
index 3d4fbebb5..0f65a7859
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -209,22 +209,22 @@ static ngx_conf_post_t  ngx_http_proxy_lowat_post =
     { ngx_http_proxy_lowat_check };
 
 
-static ngx_conf_bitmask_t  ngx_http_proxy_next_upstream_masks[] = {
-    { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
-    { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
-    { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
-    { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT },
-    { 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_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
-    { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
-    { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 },
-    { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
-    { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
-    { ngx_null_string, 0 }
-};
+//static ngx_conf_bitmask_t  ngx_http_proxy_next_upstream_masks[] = {
+//    { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
+//    { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
+//    { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
+//    { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT },
+//    { 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_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
+//    { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
+//    { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 },
+//    { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
+//    { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
+//    { ngx_null_string, 0 }
+//};
 
 
 #if (NGX_HTTP_SSL)
@@ -589,10 +589,10 @@ static ngx_command_t  ngx_http_proxy_commands[] = {
 
     { ngx_string("proxy_next_upstream"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
-      ngx_conf_set_bitmask_slot,
+	  ngx_http_set_complex_value_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream),
-      &ngx_http_proxy_next_upstream_masks },
+      offsetof(ngx_http_proxy_loc_conf_t, upstream.ar_next_upstream),
+      NULL },
 
     { ngx_string("proxy_next_upstream_tries"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
@@ -3082,15 +3082,20 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
                               NGX_CONF_BITMASK_SET);
 
 
-    ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
-                              prev->upstream.next_upstream,
-                              (NGX_CONF_BITMASK_SET
-                               |NGX_HTTP_UPSTREAM_FT_ERROR
-                               |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
+//    ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
+//                              prev->upstream.next_upstream,
+//                              (NGX_CONF_BITMASK_SET
+//                               |NGX_HTTP_UPSTREAM_FT_ERROR
+//                               |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
+//
+//
+//    if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
+//        conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
+//                                       |NGX_HTTP_UPSTREAM_FT_OFF;
+//    }
 
-    if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
-        conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
-                                       |NGX_HTTP_UPSTREAM_FT_OFF;
+    if ( conf->upstream.ar_next_upstream == NULL ){
+    	conf->upstream.ar_next_upstream = prev->upstream.ar_next_upstream ;
     }
 
     if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
old mode 100644
new mode 100755
index 60be175cb..b7f23d747
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -559,6 +559,7 @@ ngx_http_upstream_init_request(ngx_http_request_t *r)
     ngx_http_upstream_main_conf_t  *umcf;
     ngx_str_t                      ar_ignore_headers_val;
     ngx_str_t                      ar_cache_use_stale_val;
+    ngx_str_t                      ar_next_upstream_val;
 
     if (r->aio) {
         return;
@@ -618,6 +619,75 @@ ngx_http_upstream_init_request(ngx_http_request_t *r)
     }
 
 
+
+    if ((u->conf->ar_next_upstream != NULL
+            && ngx_http_complex_value(r, u->conf->ar_next_upstream, &ar_next_upstream_val) == NGX_OK)) {
+          char* ar_char_next_upstream_val;
+          ar_char_next_upstream_val = ngx_pcalloc(r->pool, sizeof(u_char) * ar_next_upstream_val.len + 1);
+          ngx_memcpy(ar_char_next_upstream_val, ar_next_upstream_val.data, sizeof(u_char) * (ar_next_upstream_val.len));
+          ar_char_next_upstream_val[ar_next_upstream_val.len] = 0;
+    	  char * pch;
+    	  pch = strtok (ar_char_next_upstream_val, " ");
+    	  u->conf->next_upstream = 0;
+    	  while (pch != NULL)
+    	  {
+
+      	    if(ngx_strncasecmp((u_char *)pch, (u_char *) "error", 5) == 0){
+      	    	u->conf->next_upstream |=  NGX_HTTP_UPSTREAM_FT_ERROR;
+      	    }
+
+      	    else if(ngx_strncasecmp((u_char *)pch, (u_char *) "timeout", 7) == 0){
+      	    	u->conf->next_upstream |=  NGX_HTTP_UPSTREAM_FT_TIMEOUT;
+    	    }
+
+      	    else if(ngx_strncasecmp((u_char *)pch, (u_char *) "invalid_header", 14) == 0){
+      	    	u->conf->next_upstream |=  NGX_HTTP_UPSTREAM_FT_INVALID_HEADER;
+    	    }
+
+      	    else if(ngx_strncasecmp((u_char *)pch, (u_char *) "non_idempotent", 14) == 0){
+      	    	u->conf->next_upstream |=  NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT;
+    	    }
+
+      	    else if(ngx_strncasecmp((u_char *)pch, (u_char *) "http_500", 8) == 0){
+      	    	u->conf->next_upstream |=  NGX_HTTP_UPSTREAM_FT_HTTP_500;
+    	    }
+
+      	    else if(ngx_strncasecmp((u_char *)pch, (u_char *) "http_502", 8) == 0){
+      	    	u->conf->next_upstream |=  NGX_HTTP_UPSTREAM_FT_HTTP_502;
+    	    }
+
+      	    else if(ngx_strncasecmp((u_char *)pch, (u_char *) "http_503", 8) == 0){
+      	    	u->conf->next_upstream |=  NGX_HTTP_UPSTREAM_FT_HTTP_503;
+    	    }
+
+      	    else if(ngx_strncasecmp((u_char *)pch, (u_char *) "http_504", 8) == 0){
+      	    	u->conf->next_upstream |=  NGX_HTTP_UPSTREAM_FT_HTTP_504;
+    	    }
+
+      	    else if(ngx_strncasecmp((u_char *)pch, (u_char *) "http_403", 8) == 0){
+      	    	u->conf->next_upstream |=  NGX_HTTP_UPSTREAM_FT_HTTP_403;
+    	    }
+
+      	    else if(ngx_strncasecmp((u_char *)pch, (u_char *) "http_404", 8) == 0){
+      	    	u->conf->next_upstream |=  NGX_HTTP_UPSTREAM_FT_HTTP_404;
+    	    }
+
+      	    else if(ngx_strncasecmp((u_char *)pch, (u_char *) "http_429", 8) == 0){
+      	    	u->conf->next_upstream |=  NGX_HTTP_UPSTREAM_FT_HTTP_429;
+    	    }
+
+      	    else if(ngx_strncasecmp((u_char *)pch, (u_char *) "updating", 8) == 0){
+      	    	u->conf->next_upstream |=  NGX_HTTP_UPSTREAM_FT_UPDATING;
+    	    }
+
+      	    else if(ngx_strncasecmp((u_char *)pch, (u_char *) "off", 3) == 0){
+      	    	u->conf->next_upstream |=  NGX_HTTP_UPSTREAM_FT_OFF;
+    	    }
+    	    pch = strtok (NULL, " ");
+    	  }
+    }
+
+
     if ((u->conf->ar_cache_use_stale != NULL
             && ngx_http_complex_value(r, u->conf->ar_cache_use_stale, &ar_cache_use_stale_val) == NGX_OK)) {
   	    if(ngx_strncasecmp((u_char *)ar_cache_use_stale_val.data, (u_char *) "on", 2) == 0){
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
old mode 100644
new mode 100755
index 2657465f4..5a85db3e8
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -171,6 +171,7 @@ typedef struct {
     ngx_uint_t                       ignore_headers;
     ngx_http_complex_value_t         *ar_ignore_headers;
     ngx_uint_t                       next_upstream;
+    ngx_http_complex_value_t         *ar_next_upstream;
     ngx_uint_t                       store_access;
     ngx_uint_t                       next_upstream_tries;
     ngx_flag_t                       buffering;
-- 
GitLab