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