[PATCH] Upstream: proxy_bind/fastcgi_bind/memcached_bind variables support

Maxim Dounin mdounin at mdounin.ru
Tue Apr 6 23:12:58 MSD 2010


# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1270581171 -14400
# Node ID c82ced18c40e3574b865428b5b48f39f2f2d388f
# Parent  0d9b939b555e0adfcfc2e4ab4fc40fd7e9d56700
Upstream: proxy_bind/fastcgi_bind/memcached_bind variables support.

While here also fixed missing inheritance for "proxy_bind", "fastcgi_bind"
and "memcached_bind" directives, and added protection against duplicate
directives.

Changes since last submit: fixed segmentation fault on bind() error.

diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -245,7 +245,7 @@ static ngx_command_t  ngx_http_fastcgi_c
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_http_upstream_bind_set_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.local),
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream),
       NULL },
 
     { ngx_string("fastcgi_connect_timeout"),
@@ -1921,6 +1921,8 @@ ngx_http_fastcgi_create_loc_conf(ngx_con
      *     conf->upstream.location = NULL;
      *     conf->upstream.store_lengths = NULL;
      *     conf->upstream.store_values = NULL;
+     *     conf->upstream.local = NULL;
+     *     conf->upstream.local_value = NULL;
      *
      *     conf->index.len = 0;
      *     conf->index.data = NULL;
@@ -2216,6 +2218,14 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
         conf->upstream.upstream = prev->upstream.upstream;
     }
 
+    if (conf->upstream.local == NULL) {
+        conf->upstream.local = prev->upstream.local;
+
+        if (conf->upstream.local_value == NULL) {
+            conf->upstream.local_value = prev->upstream.local_value;
+        }
+    }
+
     if (conf->fastcgi_lengths == NULL) {
         conf->fastcgi_lengths = prev->fastcgi_lengths;
         conf->fastcgi_values = prev->fastcgi_values;
diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c
--- a/src/http/modules/ngx_http_memcached_module.c
+++ b/src/http/modules/ngx_http_memcached_module.c
@@ -67,7 +67,7 @@ static ngx_command_t  ngx_http_memcached
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_http_upstream_bind_set_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_memcached_loc_conf_t, upstream.local),
+      offsetof(ngx_http_memcached_loc_conf_t, upstream),
       NULL },
 
     { ngx_string("memcached_connect_timeout"),
@@ -531,6 +531,8 @@ ngx_http_memcached_create_loc_conf(ngx_c
      *     conf->upstream.temp_path = NULL;
      *     conf->upstream.uri = { 0, NULL };
      *     conf->upstream.location = NULL;
+     *     conf->upstream.local = NULL;
+     *     conf->upstream.local_value = NULL;
      */
 
     conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
@@ -593,6 +595,14 @@ ngx_http_memcached_merge_loc_conf(ngx_co
         conf->upstream.upstream = prev->upstream.upstream;
     }
 
+    if (conf->upstream.local == NULL) {
+        conf->upstream.local = prev->upstream.local;
+
+        if (conf->upstream.local_value == NULL) {
+            conf->upstream.local_value = prev->upstream.local_value;
+        }
+    }
+
     if (conf->index == NGX_CONF_UNSET) {
         conf->index = prev->index;
     }
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
@@ -233,7 +233,7 @@ static ngx_command_t  ngx_http_proxy_com
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_http_upstream_bind_set_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_proxy_loc_conf_t, upstream.local),
+      offsetof(ngx_http_proxy_loc_conf_t, upstream),
       NULL },
 
     { ngx_string("proxy_connect_timeout"),
@@ -1906,6 +1906,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_
      *     conf->upstream.location = NULL;
      *     conf->upstream.store_lengths = NULL;
      *     conf->upstream.store_values = NULL;
+     *     conf->upstream.local = NULL;
+     *     conf->upstream.local_value = NULL;
      *
      *     conf->method = NULL;
      *     conf->headers_source = NULL;
@@ -2275,6 +2277,14 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
         conf->vars = prev->vars;
     }
 
+    if (conf->upstream.local == NULL) {
+        conf->upstream.local = prev->upstream.local;
+
+        if (conf->upstream.local_value == NULL) {
+            conf->upstream.local_value = prev->upstream.local_value;
+        }
+    }
+
 
     if (conf->body_source.data == NULL) {
         conf->body_source = prev->body_source;
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -26,11 +26,11 @@ typedef u_char *(*ngx_http_log_handler_p
 
 #include <ngx_http_variables.h>
 #include <ngx_http_request.h>
+#include <ngx_http_script.h>
 #include <ngx_http_upstream.h>
 #include <ngx_http_upstream_round_robin.h>
 #include <ngx_http_config.h>
 #include <ngx_http_busy_lock.h>
-#include <ngx_http_script.h>
 #include <ngx_http_core_module.h>
 
 #if (NGX_HTTP_CACHE)
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
@@ -124,6 +124,9 @@ static char *ngx_http_upstream(ngx_conf_
 static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 
+static ngx_addr_t *ngx_http_upstream_get_local(ngx_http_request_t *r,
+    ngx_http_complex_value_t *cv, ngx_addr_t *addr);
+
 static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);
 static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf);
 
@@ -480,7 +483,8 @@ ngx_http_upstream_init_request(ngx_http_
         return;
     }
 
-    u->peer.local = u->conf->local;
+    u->peer.local = ngx_http_upstream_get_local(r, u->conf->local_value,
+                                                u->conf->local);
 
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
@@ -4209,26 +4213,51 @@ char *
 ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf)
 {
-    char  *p = conf;
-
-    ngx_int_t     rc;
-    ngx_str_t    *value;
-    ngx_addr_t  **paddr;
-
-    paddr = (ngx_addr_t **) (p + cmd->offset);
-
-    *paddr = ngx_palloc(cf->pool, sizeof(ngx_addr_t));
-    if (*paddr == NULL) {
-        return NGX_CONF_ERROR;
+    ngx_http_upstream_conf_t  *upstream = conf;
+
+    ngx_int_t                          rc;
+    ngx_str_t                         *value;
+    ngx_http_complex_value_t           cv;
+    ngx_http_compile_complex_value_t   ccv;
+
+    if (upstream->local != NULL || upstream->local_value != NULL) {
+        return "is duplicate";
     }
 
     value = cf->args->elts;
 
-    rc = ngx_parse_addr(cf->pool, *paddr, value[1].data, value[1].len);
+    ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+    ccv.cf = cf;
+    ccv.value = &value[1];
+    ccv.complex_value = &cv;
+
+    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+        return NGX_CONF_ERROR;
+    }
+
+    if (cv.lengths != NULL) {
+        upstream->local_value = ngx_palloc(cf->pool,
+                                           sizeof(ngx_http_complex_value_t));
+        if (upstream->local_value == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        *upstream->local_value = cv;
+
+        return NGX_CONF_OK;
+    }
+
+    upstream->local = ngx_palloc(cf->pool, sizeof(ngx_addr_t));
+    if (upstream->local == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    rc = ngx_parse_addr(cf->pool, upstream->local, value[1].data, value[1].len);
 
     switch (rc) {
     case NGX_OK:
-        (*paddr)->name = value[1];
+        upstream->local->name = value[1];
         return NGX_CONF_OK;
 
     case NGX_DECLINED:
@@ -4240,6 +4269,49 @@ ngx_http_upstream_bind_set_slot(ngx_conf
 }
 
 
+static ngx_addr_t *
+ngx_http_upstream_get_local(ngx_http_request_t *r,
+    ngx_http_complex_value_t *cv, ngx_addr_t *addr)
+{
+    ngx_int_t    rc;
+    ngx_str_t    val;
+    ngx_addr_t  *local;
+
+    if (cv == NULL) {
+        return addr;
+    }
+
+    if (ngx_http_complex_value(r, cv, &val) != NGX_OK) {
+        return NULL;
+    }
+
+    if (val.len == 0) {
+        return NULL;
+    }
+
+    local = ngx_palloc(r->pool, sizeof(ngx_addr_t));
+    if (local == NULL) {
+        return NULL;
+    }
+
+    rc = ngx_parse_addr(r->pool, local, val.data, val.len);
+
+    switch (rc) {
+    case NGX_OK:
+        local->name = val;
+        return local;
+
+    case NGX_DECLINED:
+        ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+                      "invalid local address \"%V\"", &val);
+        return NULL;
+
+    default:
+        return NULL;
+    }
+}
+
+
 ngx_int_t
 ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
     ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
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
@@ -153,6 +153,7 @@ typedef struct {
     ngx_array_t                     *pass_headers;
 
     ngx_addr_t                      *local;
+    ngx_http_complex_value_t        *local_value;
 
 #if (NGX_HTTP_CACHE)
     ngx_shm_zone_t                  *cache;



More information about the nginx-devel mailing list