Stream: the $upstream_status variable.

Keeps status code of upstream server. The status code reflects only
the status of the upstream, not the code in the upstream response.
Status codes of several responses are separated by commas like addresses
in the $upstream_addr variable.
If a server cannot be selected, the variable keeps the 502 status code.
This commit is contained in:
Hanada 2026-04-27 10:38:50 +08:00
parent bac04c1b66
commit 9648b91ac1
3 changed files with 65 additions and 0 deletions

View file

@ -2198,6 +2198,8 @@ ngx_stream_proxy_next_upstream(ngx_stream_session_t *s)
pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module);
u->state->status = NGX_STREAM_BAD_GATEWAY;
timeout = pscf->next_upstream_timeout;
if (u->peer.tries == 0
@ -2260,6 +2262,10 @@ ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_uint_t rc)
u->state->response_time = ngx_current_msec - u->start_time;
}
if (u->state->status == 0) {
u->state->status = rc;
}
if (pc) {
u->state->bytes_received = u->received;
u->state->bytes_sent = pc->sent;

View file

@ -13,6 +13,8 @@
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 ngx_int_t ngx_stream_upstream_status_variable(ngx_stream_session_t *s,
ngx_stream_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_stream_upstream_response_time_variable(
ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_stream_upstream_bytes_variable(ngx_stream_session_t *s,
@ -103,6 +105,10 @@ static ngx_stream_variable_t ngx_stream_upstream_vars[] = {
ngx_stream_upstream_addr_variable, 0,
NGX_STREAM_VAR_NOCACHEABLE, 0 },
{ ngx_string("upstream_status"), NULL,
ngx_stream_upstream_status_variable, 0,
NGX_STREAM_VAR_NOCACHEABLE, 0 },
{ ngx_string("upstream_bytes_sent"), NULL,
ngx_stream_upstream_bytes_variable, 0,
NGX_STREAM_VAR_NOCACHEABLE, 0 },
@ -203,6 +209,58 @@ ngx_stream_upstream_addr_variable(ngx_stream_session_t *s,
}
static ngx_int_t
ngx_stream_upstream_status_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 = s->upstream_states->nelts * (3 + 2);
p = ngx_pnalloc(s->connection->pool, len);
if (p == NULL) {
return NGX_ERROR;
}
v->data = p;
i = 0;
state = s->upstream_states->elts;
for ( ;; ) {
if (state[i].status) {
p = ngx_sprintf(p, "%ui", state[i].status);
} else {
*p++ = '-';
}
if (++i == s->upstream_states->nelts) {
break;
}
*p++ = ',';
*p++ = ' ';
}
v->len = p - v->data;
return NGX_OK;
}
static ngx_int_t
ngx_stream_upstream_bytes_variable(ngx_stream_session_t *s,
ngx_stream_variable_value_t *v, uintptr_t data)

View file

@ -93,6 +93,7 @@ struct ngx_stream_upstream_srv_conf_s {
typedef struct {
ngx_uint_t status;
ngx_msec_t response_time;
ngx_msec_t connect_time;
ngx_msec_t first_byte_time;