Stream: the $upstream_addr variable.

Keeps the full address of the upstream server.  If several servers were
contacted during proxying, their addresses are separated by commas,
e.g. "192.168.1.1:80, 192.168.1.2:80".
This commit is contained in:
Vladimir Homutov 2016-09-02 18:27:05 +03:00
parent be6024f9b7
commit c6d456da87
4 changed files with 116 additions and 2 deletions

View File

@ -172,7 +172,8 @@ struct ngx_stream_session_s {
void **srv_conf; void **srv_conf;
ngx_stream_upstream_t *upstream; ngx_stream_upstream_t *upstream;
ngx_array_t *upstream_states;
/* of ngx_stream_upstream_state_t */
ngx_stream_variable_value_t *variables; ngx_stream_variable_value_t *variables;
#if (NGX_PCRE) #if (NGX_PCRE)

View File

@ -392,6 +392,13 @@ ngx_stream_proxy_handler(ngx_stream_session_t *s)
c->write->handler = ngx_stream_proxy_downstream_handler; c->write->handler = ngx_stream_proxy_downstream_handler;
c->read->handler = ngx_stream_proxy_downstream_handler; c->read->handler = ngx_stream_proxy_downstream_handler;
s->upstream_states = ngx_array_create(c->pool, 1,
sizeof(ngx_stream_upstream_state_t));
if (s->upstream_states == NULL) {
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return;
}
if (c->type == SOCK_STREAM) { if (c->type == SOCK_STREAM) {
p = ngx_pnalloc(c->pool, pscf->buffer_size); p = ngx_pnalloc(c->pool, pscf->buffer_size);
if (p == NULL) { if (p == NULL) {
@ -677,6 +684,14 @@ ngx_stream_proxy_connect(ngx_stream_session_t *s)
u = s->upstream; u = s->upstream;
u->state = ngx_array_push(s->upstream_states);
if (u->state == NULL) {
ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
return;
}
ngx_memzero(u->state, sizeof(ngx_stream_upstream_state_t));
rc = ngx_event_connect_peer(&u->peer); rc = ngx_event_connect_peer(&u->peer);
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "proxy connect: %i", rc); ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "proxy connect: %i", rc);
@ -686,6 +701,8 @@ ngx_stream_proxy_connect(ngx_stream_session_t *s)
return; return;
} }
u->state->peer = u->peer.name;
if (rc == NGX_BUSY) { if (rc == NGX_BUSY) {
ngx_log_error(NGX_LOG_ERR, c->log, 0, "no live upstreams"); ngx_log_error(NGX_LOG_ERR, c->log, 0, "no live upstreams");
ngx_stream_proxy_finalize(s, NGX_STREAM_BAD_GATEWAY); ngx_stream_proxy_finalize(s, NGX_STREAM_BAD_GATEWAY);

View File

@ -10,6 +10,10 @@
#include <ngx_stream.h> #include <ngx_stream.h>
static ngx_int_t ngx_stream_upstream_add_variables(ngx_conf_t *cf);
static ngx_int_t ngx_stream_upstream_addr_variable(ngx_stream_session_t *s,
ngx_stream_variable_value_t *v, uintptr_t data);
static char *ngx_stream_upstream(ngx_conf_t *cf, ngx_command_t *cmd, static char *ngx_stream_upstream(ngx_conf_t *cf, ngx_command_t *cmd,
void *dummy); void *dummy);
static char *ngx_stream_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, static char *ngx_stream_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd,
@ -39,7 +43,7 @@ static ngx_command_t ngx_stream_upstream_commands[] = {
static ngx_stream_module_t ngx_stream_upstream_module_ctx = { static ngx_stream_module_t ngx_stream_upstream_module_ctx = {
NULL, /* preconfiguration */ ngx_stream_upstream_add_variables, /* preconfiguration */
NULL, /* postconfiguration */ NULL, /* postconfiguration */
ngx_stream_upstream_create_main_conf, /* create main configuration */ ngx_stream_upstream_create_main_conf, /* create main configuration */
@ -66,6 +70,92 @@ ngx_module_t ngx_stream_upstream_module = {
}; };
static ngx_stream_variable_t ngx_stream_upstream_vars[] = {
{ ngx_string("upstream_addr"), NULL,
ngx_stream_upstream_addr_variable, 0,
NGX_STREAM_VAR_NOCACHEABLE, 0 },
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
};
static ngx_int_t
ngx_stream_upstream_add_variables(ngx_conf_t *cf)
{
ngx_stream_variable_t *var, *v;
for (v = ngx_stream_upstream_vars; v->name.len; v++) {
var = ngx_stream_add_variable(cf, &v->name, v->flags);
if (var == NULL) {
return NGX_ERROR;
}
var->get_handler = v->get_handler;
var->data = v->data;
}
return NGX_OK;
}
static ngx_int_t
ngx_stream_upstream_addr_variable(ngx_stream_session_t *s,
ngx_stream_variable_value_t *v, uintptr_t data)
{
u_char *p;
size_t len;
ngx_uint_t i;
ngx_stream_upstream_state_t *state;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
if (s->upstream_states == NULL || s->upstream_states->nelts == 0) {
v->not_found = 1;
return NGX_OK;
}
len = 0;
state = s->upstream_states->elts;
for (i = 0; i < s->upstream_states->nelts; i++) {
if (state[i].peer) {
len += state[i].peer->len;
}
len += 2;
}
p = ngx_pnalloc(s->connection->pool, len);
if (p == NULL) {
return NGX_ERROR;
}
v->data = p;
i = 0;
for ( ;; ) {
if (state[i].peer) {
p = ngx_cpymem(p, state[i].peer->data, state[i].peer->len);
}
if (++i == s->upstream_states->nelts) {
break;
}
*p++ = ',';
*p++ = ' ';
}
v->len = p - v->data;
return NGX_OK;
}
static char * static char *
ngx_stream_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) ngx_stream_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
{ {

View File

@ -78,6 +78,11 @@ struct ngx_stream_upstream_srv_conf_s {
}; };
typedef struct {
ngx_str_t *peer;
} ngx_stream_upstream_state_t;
typedef struct { typedef struct {
ngx_str_t host; ngx_str_t host;
in_port_t port; in_port_t port;
@ -104,6 +109,7 @@ typedef struct {
ngx_str_t ssl_name; ngx_str_t ssl_name;
#endif #endif
ngx_stream_upstream_resolved_t *resolved; ngx_stream_upstream_resolved_t *resolved;
ngx_stream_upstream_state_t *state;
unsigned connected:1; unsigned connected:1;
unsigned proxy_protocol:1; unsigned proxy_protocol:1;
} ngx_stream_upstream_t; } ngx_stream_upstream_t;