[PATCH] HTTP upstream: added possibility to specify variables for the ip_hash directive
Alexey K.
alexeyk45 at gmail.com
Thu May 22 07:32:48 UTC 2014
# HG changeset patch
# User Alexey K. <alexeyk45 at gmail.com>
# 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;
};
More information about the nginx-devel
mailing list