<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>