<div dir="ltr">Im not sure that patch would suit my needs, simply because most of the time I am matching on the upstream address only and need it to work regardless of the port (i.e a regex match on just the IP component).<div>
<br></div><div>Perhaps your patch could be extended to support -</div><div><br></div><div><span style="font-family:arial,sans-serif;font-size:13px">map $upstream_peer_addr $bind_addr {</span><br style="font-family:arial,sans-serif;font-size:13px">
<span style="font-family:arial,sans-serif;font-size:13px"> </span><a href="http://127.0.0.1:8001/" target="_blank" style="font-family:arial,sans-serif;font-size:13px">127.0.0.1:8001</a><span style="font-family:arial,sans-serif;font-size:13px"> 127.0.0.1;</span><br style="font-family:arial,sans-serif;font-size:13px">
<span style="font-family:arial,sans-serif;font-size:13px"> </span><a href="http://127.0.0.1:8002/" target="_blank" style="font-family:arial,sans-serif;font-size:13px">127.0.0.2</a><span style="font-family:arial,sans-serif;font-size:13px"> 127.0.0.1;</span><br style="font-family:arial,sans-serif;font-size:13px">
<span style="font-family:arial,sans-serif;font-size:13px"> [::1]:8003 ::1;</span><br style="font-family:arial,sans-serif;font-size:13px"><span style="font-family:arial,sans-serif;font-size:13px">}</span><br></div><div>
<span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">Where 127.0.0.2 would match 127.0.0.2:*</span></div><div><span style="font-family:arial,sans-serif;font-size:13px"><br>
</span></div><div><font face="arial, sans-serif">I certainly like that it doesn't require a conversion to string.</font></div><div><font face="arial, sans-serif"><br></font></div><div><font face="arial, sans-serif">I have also attached V2 of my patch (changes to the patch to remove windows path style).</font></div>
</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Dec 9, 2013 at 8:59 PM, Ruslan Ermilov <span dir="ltr"><<a href="mailto:ru@nginx.com" target="_blank">ru@nginx.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im">On Sat, Nov 23, 2013 at 12:15:28PM +1030, SplitIce wrote:<br>
> Attached is the patch,<br>
><br>
> This is the first time I have created a variable or really done anything<br>
> inside the http request processing flow so feel free to let me know if<br>
> there is a better way to do something or if I have any edge cases.<br>
><br>
> This patch provides a $upstream_connecting variable which contains the IP<br>
> address and port of the upstream being connected. If there is no upstream,<br>
> it will return "-" my understanding is this may happen if the upstream is<br>
> DNS resolved (untested). There may be a better way of doing this?<br>
><br>
> This should be used in a config like the following -<br>
> map $upstream_connecting $test {<br>
> ~^93\.184\.216\.119\: 192.168.2.40;<br>
> ~^192\.168\.2\.([0-9]+)\: 192.168.2.40;<br>
> }<br>
><br>
> proxy_bind $test;<br>
<br>
</div>I took a different approach. I've made "local" a peer's method,<br>
so the computation of the local address is delayed until it's<br>
actually needed. By that time, the peer address is already known.<br>
<br>
I've also patched "map" so it creates non-cacheable variables.<br>
<br>
This way, $upstream_peer_addr can be mapped into the local address:<br>
<br>
map $upstream_peer_addr $bind_addr {<br>
<a href="http://127.0.0.1:8001" target="_blank">127.0.0.1:8001</a> 127.0.0.1;<br>
<a href="http://127.0.0.1:8002" target="_blank">127.0.0.1:8002</a> 127.0.0.1;<br>
[::1]:8003 ::1;<br>
}<br>
<br>
server {<br>
...<br>
location / {<br>
proxy_pass ...;<br>
proxy_bind $bind_addr;<br>
...<br>
}<br>
}<br>
<br>
diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c<br>
--- a/src/event/ngx_event_connect.c<br>
+++ b/src/event/ngx_event_connect.c<br>
@@ -17,6 +17,7 @@ ngx_event_connect_peer(ngx_peer_connecti<br>
int rc;<br>
ngx_int_t event;<br>
ngx_err_t err;<br>
+ ngx_addr_t *local;<br>
ngx_uint_t level;<br>
ngx_socket_t s;<br>
ngx_event_t *rev, *wev;<br>
@@ -67,9 +68,13 @@ ngx_event_connect_peer(ngx_peer_connecti<br>
}<br>
<br>
if (pc->local) {<br>
- if (bind(s, pc->local->sockaddr, pc->local->socklen) == -1) {<br>
+ local = pc->local(pc, pc->data);<br>
+<br>
+ if (local != NULL<br>
+ && bind(s, local->sockaddr, local->socklen) == -1)<br>
+ {<br>
ngx_log_error(NGX_LOG_CRIT, pc->log, ngx_socket_errno,<br>
- "bind(%V) failed", &pc->local->name);<br>
+ "bind(%V) failed", &local->name);<br>
<br>
goto failed;<br>
}<br>
diff --git a/src/event/ngx_event_connect.h b/src/event/ngx_event_connect.h<br>
--- a/src/event/ngx_event_connect.h<br>
+++ b/src/event/ngx_event_connect.h<br>
@@ -25,6 +25,8 @@ typedef ngx_int_t (*ngx_event_get_peer_p<br>
void *data);<br>
typedef void (*ngx_event_free_peer_pt)(ngx_peer_connection_t *pc, void *data,<br>
ngx_uint_t state);<br>
+typedef ngx_addr_t *(*ngx_event_get_local_pt)(ngx_peer_connection_t *pc,<br>
+ void *data);<br>
#if (NGX_SSL)<br>
<br>
typedef ngx_int_t (*ngx_event_set_peer_session_pt)(ngx_peer_connection_t *pc,<br>
@@ -45,6 +47,7 @@ struct ngx_peer_connection_s {<br>
<br>
ngx_event_get_peer_pt get;<br>
ngx_event_free_peer_pt free;<br>
+ ngx_event_get_local_pt local;<br>
void *data;<br>
<br>
#if (NGX_SSL)<br>
@@ -56,8 +59,6 @@ struct ngx_peer_connection_s {<br>
ngx_atomic_t *lock;<br>
#endif<br>
<br>
- ngx_addr_t *local;<br>
-<br>
int rcvbuf;<br>
<br>
ngx_log_t *log;<br>
diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c<br>
--- a/src/http/modules/ngx_http_map_module.c<br>
+++ b/src/http/modules/ngx_http_map_module.c<br>
@@ -477,7 +477,7 @@ ngx_http_map(ngx_conf_t *cf, ngx_command<br>
}<br>
<br>
var->valid = 1;<br>
- var->no_cacheable = 0;<br>
+ var->no_cacheable = 1;<br>
var->not_found = 0;<br>
<br>
vp = ngx_array_push(&ctx->values_hash[key]);<br>
diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c b/src/http/modules/ngx_http_upstream_keepalive_module.c<br>
--- a/src/http/modules/ngx_http_upstream_keepalive_module.c<br>
+++ b/src/http/modules/ngx_http_upstream_keepalive_module.c<br>
@@ -31,6 +31,7 @@ typedef struct {<br>
<br>
ngx_event_get_peer_pt original_get_peer;<br>
ngx_event_free_peer_pt original_free_peer;<br>
+ ngx_event_get_local_pt original_get_local;<br>
<br>
#if (NGX_HTTP_SSL)<br>
ngx_event_set_peer_session_pt original_set_session;<br>
@@ -63,6 +64,9 @@ static void ngx_http_upstream_keepalive_<br>
static void ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev);<br>
static void ngx_http_upstream_keepalive_close(ngx_connection_t *c);<br>
<br>
+static ngx_addr_t *ngx_http_upstream_get_keepalive_local(<br>
+ ngx_peer_connection_t *pc, void *data);<br>
+<br>
<br>
#if (NGX_HTTP_SSL)<br>
static ngx_int_t ngx_http_upstream_keepalive_set_session(<br>
@@ -189,10 +193,12 @@ ngx_http_upstream_init_keepalive_peer(ng<br>
kp->data = r->upstream->peer.data;<br>
kp->original_get_peer = r->upstream->peer.get;<br>
kp->original_free_peer = r->upstream->peer.free;<br>
+ kp->original_get_local = r->upstream->peer.local;<br>
<br>
r->upstream->peer.data = kp;<br>
r->upstream->peer.get = ngx_http_upstream_get_keepalive_peer;<br>
r->upstream->peer.free = ngx_http_upstream_free_keepalive_peer;<br>
+ r->upstream->peer.local = ngx_http_upstream_get_keepalive_local;<br>
<br>
#if (NGX_HTTP_SSL)<br>
kp->original_set_session = r->upstream->peer.set_session;<br>
@@ -430,6 +436,16 @@ ngx_http_upstream_keepalive_close(ngx_co<br>
}<br>
<br>
<br>
+static ngx_addr_t *<br>
+ngx_http_upstream_get_keepalive_local(ngx_peer_connection_t *pc,<br>
+ void *data)<br>
+{<br>
+ ngx_http_upstream_keepalive_peer_data_t *kp = data;<br>
+<br>
+ return kp->original_get_local(pc, kp->data);<br>
+}<br>
+<br>
+<br>
#if (NGX_HTTP_SSL)<br>
<br>
static ngx_int_t<br>
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c<br>
--- a/src/http/ngx_http_upstream.c<br>
+++ b/src/http/ngx_http_upstream.c<br>
@@ -141,14 +141,13 @@ static ngx_int_t ngx_http_upstream_respo<br>
ngx_http_variable_value_t *v, uintptr_t data);<br>
static ngx_int_t ngx_http_upstream_response_length_variable(<br>
ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);<br>
+static ngx_int_t ngx_http_upstream_peer_addr_variable(ngx_http_request_t *r,<br>
+ ngx_http_variable_value_t *v, uintptr_t data);<br>
<br>
static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy);<br>
static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd,<br>
void *conf);<br>
<br>
-static ngx_addr_t *ngx_http_upstream_get_local(ngx_http_request_t *r,<br>
- ngx_http_upstream_local_t *local);<br>
-<br>
static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);<br>
static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf);<br>
<br>
@@ -366,6 +365,10 @@ static ngx_http_variable_t ngx_http_ups<br>
<br>
#endif<br>
<br>
+ { ngx_string("upstream_peer_addr"), NULL,<br>
+ ngx_http_upstream_peer_addr_variable, 0,<br>
+ NGX_HTTP_VAR_NOCACHEABLE, 0 },<br>
+<br>
{ ngx_null_string, NULL, NULL, 0, 0, 0 }<br>
};<br>
<br>
@@ -534,8 +537,6 @@ ngx_http_upstream_init_request(ngx_http_<br>
return;<br>
}<br>
<br>
- u->peer.local = ngx_http_upstream_get_local(r, u->conf->local);<br>
-<br>
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);<br>
<br>
u->output.alignment = clcf->directio_alignment;<br>
@@ -4509,6 +4510,25 @@ ngx_http_upstream_response_length_variab<br>
}<br>
<br>
<br>
+static ngx_int_t<br>
+ngx_http_upstream_peer_addr_variable(ngx_http_request_t *r,<br>
+ ngx_http_variable_value_t *v, uintptr_t data)<br>
+{<br>
+ if (r->upstream == NULL || r->upstream-><a href="http://peer.name" target="_blank">peer.name</a> == NULL) {<br>
+ v->not_found = 1;<br>
+ return NGX_OK;<br>
+ }<br>
+<br>
+ v->len = r->upstream->peer.name->len;<br>
+ v->data = r->upstream->peer.name->data;<br>
+ v->valid = 1;<br>
+ v->no_cacheable = 0;<br>
+ v->not_found = 0;<br>
+<br>
+ return NGX_OK;<br>
+}<br>
+<br>
+<br>
ngx_int_t<br>
ngx_http_upstream_header_variable(ngx_http_request_t *r,<br>
ngx_http_variable_value_t *v, uintptr_t data)<br>
@@ -5022,53 +5042,6 @@ ngx_http_upstream_bind_set_slot(ngx_conf<br>
}<br>
<br>
<br>
-static ngx_addr_t *<br>
-ngx_http_upstream_get_local(ngx_http_request_t *r,<br>
- ngx_http_upstream_local_t *local)<br>
-{<br>
- ngx_int_t rc;<br>
- ngx_str_t val;<br>
- ngx_addr_t *addr;<br>
-<br>
- if (local == NULL) {<br>
- return NULL;<br>
- }<br>
-<br>
- if (local->value == NULL) {<br>
- return local->addr;<br>
- }<br>
-<br>
- if (ngx_http_complex_value(r, local->value, &val) != NGX_OK) {<br>
- return NULL;<br>
- }<br>
-<br>
- if (val.len == 0) {<br>
- return NULL;<br>
- }<br>
-<br>
- addr = ngx_palloc(r->pool, sizeof(ngx_addr_t));<br>
- if (addr == NULL) {<br>
- return NULL;<br>
- }<br>
-<br>
- rc = ngx_parse_addr(r->pool, addr, val.data, val.len);<br>
-<br>
- switch (rc) {<br>
- case NGX_OK:<br>
- addr->name = val;<br>
- return addr;<br>
-<br>
- case NGX_DECLINED:<br>
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,<br>
- "invalid local address \"%V\"", &val);<br>
- /* fall through */<br>
-<br>
- default:<br>
- return NULL;<br>
- }<br>
-}<br>
-<br>
-<br>
char *<br>
ngx_http_upstream_param_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,<br>
void *conf)<br>
diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c<br>
--- a/src/http/ngx_http_upstream_round_robin.c<br>
+++ b/src/http/ngx_http_upstream_round_robin.c<br>
@@ -22,6 +22,9 @@ static void ngx_http_upstream_empty_save<br>
<br>
#endif<br>
<br>
+static ngx_addr_t *ngx_http_upstream_get_local(ngx_peer_connection_t *pc,<br>
+ void *data);<br>
+<br>
<br>
ngx_int_t<br>
ngx_http_upstream_init_round_robin(ngx_conf_t *cf,<br>
@@ -246,6 +249,8 @@ ngx_http_upstream_init_round_robin_peer(<br>
}<br>
}<br>
<br>
+ rrp->request = r;<br>
+<br>
r->upstream->peer.get = ngx_http_upstream_get_round_robin_peer;<br>
r->upstream->peer.free = ngx_http_upstream_free_round_robin_peer;<br>
r->upstream->peer.tries = rrp->peers->number;<br>
@@ -255,6 +260,7 @@ ngx_http_upstream_init_round_robin_peer(<br>
r->upstream->peer.save_session =<br>
ngx_http_upstream_save_round_robin_peer_session;<br>
#endif<br>
+ r->upstream->peer.local = ngx_http_upstream_get_local;<br>
<br>
return NGX_OK;<br>
}<br>
@@ -679,3 +685,56 @@ ngx_http_upstream_empty_save_session(ngx<br>
}<br>
<br>
#endif<br>
+<br>
+<br>
+static ngx_addr_t *<br>
+ngx_http_upstream_get_local(ngx_peer_connection_t *pc, void *data)<br>
+{<br>
+ ngx_http_upstream_rr_peer_data_t *rrp = data;<br>
+<br>
+ ngx_int_t rc;<br>
+ ngx_str_t val;<br>
+ ngx_addr_t *addr;<br>
+ ngx_http_request_t *r;<br>
+ ngx_http_upstream_local_t *local;<br>
+<br>
+ r = rrp->request;<br>
+ local = r->upstream->conf->local;<br>
+<br>
+ if (local == NULL) {<br>
+ return NULL;<br>
+ }<br>
+<br>
+ if (local->value == NULL) {<br>
+ return local->addr;<br>
+ }<br>
+<br>
+ if (ngx_http_complex_value(r, local->value, &val) != NGX_OK) {<br>
+ return NULL;<br>
+ }<br>
+<br>
+ if (val.len == 0) {<br>
+ return NULL;<br>
+ }<br>
+<br>
+ addr = ngx_palloc(r->pool, sizeof(ngx_addr_t));<br>
+ if (addr == NULL) {<br>
+ return NULL;<br>
+ }<br>
+<br>
+ rc = ngx_parse_addr(r->pool, addr, val.data, val.len);<br>
+<br>
+ switch (rc) {<br>
+ case NGX_OK:<br>
+ addr->name = val;<br>
+ return addr;<br>
+<br>
+ case NGX_DECLINED:<br>
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,<br>
+ "invalid local address \"%V\"", &val);<br>
+ /* fall through */<br>
+<br>
+ default:<br>
+ return NULL;<br>
+ }<br>
+}<br>
diff --git a/src/http/ngx_http_upstream_round_robin.h b/src/http/ngx_http_upstream_round_robin.h<br>
--- a/src/http/ngx_http_upstream_round_robin.h<br>
+++ b/src/http/ngx_http_upstream_round_robin.h<br>
@@ -63,6 +63,7 @@ typedef struct {<br>
ngx_uint_t current;<br>
uintptr_t *tried;<br>
uintptr_t data;<br>
+ ngx_http_request_t *request;<br>
} ngx_http_upstream_rr_peer_data_t;<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
<br>
_______________________________________________<br>
nginx-devel mailing list<br>
<a href="mailto:nginx-devel@nginx.org">nginx-devel@nginx.org</a><br>
<a href="http://mailman.nginx.org/mailman/listinfo/nginx-devel" target="_blank">http://mailman.nginx.org/mailman/listinfo/nginx-devel</a><br>
</div></div></blockquote></div><br></div>