# HG changeset patch
# User Alexey K. <[email protected]>
# Date 1400743228 -21600
#      Thu May 22 13:20:28 2014 +0600
# Node ID cbfb9bc7dc93c10baaa80571665ca1231afdafe9
# Parent  d5b8ee9f2201e1d9fa7ac41da9a4a8d939cd42b1
HTTP upstream: added possibility to specify variables for the ip_hash directive.

Example: ip_hash $http_x_forwarded_for;
By default, without any parameters, client's IP address is used.

A use case:
A group of load balancers is put behind another group. Thus client's IP address for the former is always one of the latter's. With this patch ip_hash can use any variable with a valid address, including the one in X-Forwarded-For header.

diff -r d5b8ee9f2201 -r cbfb9bc7dc93 src/http/modules/ngx_http_upstream_ip_hash_module.c --- a/src/http/modules/ngx_http_upstream_ip_hash_module.c Thu May 22 00:16:17 2014 +0400 +++ b/src/http/modules/ngx_http_upstream_ip_hash_module.c Thu May 22 13:20:28 2014 +0600
@@ -36,7 +36,7 @@
 static ngx_command_t  ngx_http_upstream_ip_hash_commands[] = {

     { ngx_string("ip_hash"),
-      NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,
+      NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1,
       ngx_http_upstream_ip_hash,
       0,
       0,
@@ -116,17 +116,41 @@

     r->upstream->peer.get = ngx_http_upstream_get_ip_hash_peer;

-    switch (r->connection->sockaddr->sa_family) {
+    struct sockaddr *addr=r->connection->sockaddr;
+
+    if(us->ip_hash_var != -1) {
+
+ ngx_http_variable_value_t *v=ngx_http_get_flushed_variable(r,us->ip_hash_var);
+
+        if (v == NULL || v->not_found) {
+            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                    "http upstream ip_hash variable not found");
+        } else {
+
+            ngx_addr_t ngx_addr;
+
+ if (ngx_parse_addr(r->pool, &ngx_addr, v->data, v->len) == NGX_OK) {
+                addr=ngx_addr.sockaddr;
+            } else {
+                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                        "http upstream ip_hash address is invalid");
+            }
+
+        }
+
+    }
+
+    switch (addr->sa_family) {

     case AF_INET:
-        sin = (struct sockaddr_in *) r->connection->sockaddr;
+        sin = (struct sockaddr_in *) addr;
         iphp->addr = (u_char *) &sin->sin_addr.s_addr;
         iphp->addrlen = 3;
         break;

 #if (NGX_HAVE_INET6)
     case AF_INET6:
-        sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
+        sin6 = (struct sockaddr_in6 *) addr;
         iphp->addr = (u_char *) &sin6->sin6_addr.s6_addr;
         iphp->addrlen = 16;
         break;
@@ -267,6 +291,31 @@
                            "load balancing method redefined");
     }

+    if (cf->args->nelts == 2) {
+
+        ngx_str_t   name;
+
+        name=((ngx_str_t *)cf->args->elts)[1];
+
+        if (name.data[0] != '$') {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                    "invalid variable name \"%V\"", &name);
+            return NGX_CONF_ERROR;
+        }
+
+        name.len--;
+        name.data++;
+
+        uscf->ip_hash_var = ngx_http_get_variable_index(cf, &name);
+
+        if (uscf->ip_hash_var == NGX_ERROR) {
+            return NGX_CONF_ERROR;
+        }
+
+    } else {
+        uscf->ip_hash_var = -1;
+    }
+
     uscf->peer.init_upstream = ngx_http_upstream_init_ip_hash;

     uscf->flags = NGX_HTTP_UPSTREAM_CREATE
diff -r d5b8ee9f2201 -r cbfb9bc7dc93 src/http/ngx_http_upstream.h
--- a/src/http/ngx_http_upstream.h      Thu May 22 00:16:17 2014 +0400
+++ b/src/http/ngx_http_upstream.h      Thu May 22 13:20:28 2014 +0600
@@ -119,6 +119,7 @@
     in_port_t                        port;
     in_port_t                        default_port;
     ngx_uint_t                       no_port;  /* unsigned no_port:1 */
+    ngx_int_t                        ip_hash_var;
 };

_______________________________________________
nginx-devel mailing list
[email protected]
http://mailman.nginx.org/mailman/listinfo/nginx-devel

Reply via email to