# HG changeset patch # User Roman Arutyunyan # Date 1470936143 -10800 # Node ID 38143d1abdec9112c629be39cf675c1fd7c26ccf # Parent e4c1f5b3286887a5d8851a1686c9c3ad873eb7ee Stream: the $status variable. The stream session status is one of the following: 200 - normal completion 403 - access forbidden 500 - internal server error 502 - bad gateway 503 - limit conn diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h +++ b/src/stream/ngx_stream.h @@ -26,6 +26,13 @@ typedef struct ngx_stream_session_s ngx #include +#define NGX_STREAM_OK 200 +#define NGX_STREAM_FORBIDDEN 403 +#define NGX_STREAM_INTERNAL_SERVER_ERROR 500 +#define NGX_STREAM_BAD_GATEWAY 502 +#define NGX_STREAM_SERVICE_UNAVAILABLE 503 + + typedef struct { void **main_conf; void **srv_conf; @@ -173,6 +180,8 @@ struct ngx_stream_session_s { int *captures; u_char *captures_data; #endif + + ngx_uint_t status; }; @@ -223,7 +232,7 @@ typedef struct { void ngx_stream_init_connection(ngx_connection_t *c); -void ngx_stream_close_connection(ngx_connection_t *c); +void ngx_stream_finalize_session(ngx_stream_session_t *s, ngx_uint_t rc); extern ngx_module_t ngx_stream_module; diff --git a/src/stream/ngx_stream_handler.c b/src/stream/ngx_stream_handler.c --- a/src/stream/ngx_stream_handler.c +++ b/src/stream/ngx_stream_handler.c @@ -11,6 +11,7 @@ #include +static void ngx_stream_close_connection(ngx_connection_t *c); static u_char *ngx_stream_log_error(ngx_log_t *log, u_char *buf, size_t len); static void ngx_stream_init_session(ngx_connection_t *c); @@ -166,8 +167,13 @@ ngx_stream_init_connection(ngx_connectio if (cmcf->limit_conn_handler) { rc = cmcf->limit_conn_handler(s); - if (rc != NGX_DECLINED) { - ngx_stream_close_connection(c); + if (rc == NGX_ERROR) { + ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); + return; + } + + if (rc == NGX_ABORT) { + ngx_stream_finalize_session(s, NGX_STREAM_SERVICE_UNAVAILABLE); return; } } @@ -175,8 +181,13 @@ ngx_stream_init_connection(ngx_connectio if (cmcf->access_handler) { rc = cmcf->access_handler(s); - if (rc != NGX_OK && rc != NGX_DECLINED) { - ngx_stream_close_connection(c); + if (rc == NGX_ERROR) { + ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); + return; + } + + if (rc == NGX_ABORT) { + ngx_stream_finalize_session(s, NGX_STREAM_FORBIDDEN); return; } } @@ -194,7 +205,7 @@ ngx_stream_init_connection(ngx_connectio { ngx_connection_error(c, ngx_socket_errno, "setsockopt(TCP_NODELAY) failed"); - ngx_stream_close_connection(c); + ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -215,7 +226,7 @@ ngx_stream_init_connection(ngx_connectio ngx_log_error(NGX_LOG_ERR, c->log, 0, "no \"ssl_certificate\" is defined " "in server listening on SSL port"); - ngx_stream_close_connection(c); + ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -242,7 +253,7 @@ ngx_stream_init_session(ngx_connection_t s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_stream_max_module); if (s->ctx == NULL) { - ngx_stream_close_connection(c); + ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -258,15 +269,14 @@ ngx_stream_ssl_init_connection(ngx_ssl_t ngx_stream_session_t *s; ngx_stream_ssl_conf_t *sslcf; + s = c->data; + if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) { - ngx_stream_close_connection(c); + ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } if (ngx_ssl_handshake(c) == NGX_AGAIN) { - - s = c->data; - sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module); ngx_add_timer(c->read, sslcf->handshake_timeout); @@ -284,7 +294,7 @@ static void ngx_stream_ssl_handshake_handler(ngx_connection_t *c) { if (!c->ssl->handshaked) { - ngx_stream_close_connection(c); + ngx_stream_finalize_session(c->data, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -299,6 +309,18 @@ ngx_stream_ssl_handshake_handler(ngx_con void +ngx_stream_finalize_session(ngx_stream_session_t *s, ngx_uint_t rc) +{ + ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, + "finalize stream session: %i", rc); + + s->status = rc; + + ngx_stream_close_connection(s->connection); +} + + +static void ngx_stream_close_connection(ngx_connection_t *c) { ngx_pool_t *pool; diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c @@ -73,7 +73,7 @@ static ngx_int_t ngx_stream_proxy_test_c static void ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, ngx_uint_t do_write); static void ngx_stream_proxy_next_upstream(ngx_stream_session_t *s); -static void ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_int_t rc); +static void ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_uint_t rc); static u_char *ngx_stream_proxy_log_error(ngx_log_t *log, u_char *buf, size_t len); @@ -368,7 +368,7 @@ ngx_stream_proxy_handler(ngx_stream_sess u = ngx_pcalloc(c->pool, sizeof(ngx_stream_upstream_t)); if (u == NULL) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -380,7 +380,7 @@ ngx_stream_proxy_handler(ngx_stream_sess u->peer.log_error = NGX_ERROR_ERR; if (ngx_stream_proxy_set_local(s, u, pscf->local) != NGX_OK) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -395,7 +395,7 @@ ngx_stream_proxy_handler(ngx_stream_sess if (c->type == SOCK_STREAM) { p = ngx_pnalloc(c->pool, pscf->buffer_size); if (p == NULL) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -418,7 +418,7 @@ ngx_stream_proxy_handler(ngx_stream_sess p = ngx_proxy_protocol_write(c, u->downstream_buf.last, u->downstream_buf.end); if (p == NULL) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -433,7 +433,7 @@ ngx_stream_proxy_handler(ngx_stream_sess if (pscf->upstream_value) { if (ngx_stream_proxy_eval(s, pscf) != NGX_OK) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } } @@ -457,14 +457,14 @@ ngx_stream_proxy_handler(ngx_stream_sess { ngx_log_error(NGX_LOG_ERR, c->log, 0, "no port in upstream \"%V\"", host); - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } if (ngx_stream_upstream_create_round_robin_peer(s, u->resolved) != NGX_OK) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -493,7 +493,7 @@ ngx_stream_proxy_handler(ngx_stream_sess if (u->resolved->port == 0) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "no port in upstream \"%V\"", host); - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -503,14 +503,14 @@ ngx_stream_proxy_handler(ngx_stream_sess ctx = ngx_resolve_start(cscf->resolver, &temp); if (ctx == NULL) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } if (ctx == NGX_NO_RESOLVER) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "no resolver defined to resolve %V", host); - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -523,7 +523,7 @@ ngx_stream_proxy_handler(ngx_stream_sess if (ngx_resolve_name(ctx) != NGX_OK) { u->resolved->ctx = NULL; - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -534,7 +534,7 @@ found: if (uscf == NULL) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "no upstream configuration"); - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -543,7 +543,7 @@ found: #endif if (uscf->peer.init(s, uscf) != NGX_OK) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -682,13 +682,13 @@ ngx_stream_proxy_connect(ngx_stream_sess ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "proxy connect: %i", rc); if (rc == NGX_ERROR) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } if (rc == NGX_BUSY) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "no live upstreams"); - ngx_stream_proxy_finalize(s, NGX_DECLINED); + ngx_stream_proxy_finalize(s, NGX_STREAM_BAD_GATEWAY); return; } @@ -801,7 +801,7 @@ ngx_stream_proxy_init_upstream(ngx_strea if (u->upstream_buf.start == NULL) { p = ngx_pnalloc(c->pool, pscf->buffer_size); if (p == NULL) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -851,7 +851,7 @@ ngx_stream_proxy_send_proxy_protocol(ngx p = ngx_proxy_protocol_write(c, buf, buf + NGX_PROXY_PROTOCOL_MAX_HEADER); if (p == NULL) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return NGX_ERROR; } @@ -865,7 +865,7 @@ ngx_stream_proxy_send_proxy_protocol(ngx if (n == NGX_AGAIN) { if (ngx_handle_write_event(pc->write, 0) != NGX_OK) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return NGX_ERROR; } @@ -879,7 +879,7 @@ ngx_stream_proxy_send_proxy_protocol(ngx } if (n == NGX_ERROR) { - ngx_stream_proxy_finalize(s, NGX_DECLINED); + ngx_stream_proxy_finalize(s, NGX_STREAM_OK); return NGX_ERROR; } @@ -895,7 +895,7 @@ ngx_stream_proxy_send_proxy_protocol(ngx ngx_log_error(NGX_LOG_ERR, c->log, 0, "could not send PROXY protocol header at once"); - ngx_stream_proxy_finalize(s, NGX_DECLINED); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return NGX_ERROR; } @@ -947,20 +947,20 @@ ngx_stream_proxy_ssl_init_connection(ngx if (ngx_ssl_create_connection(pscf->ssl, pc, NGX_SSL_BUFFER|NGX_SSL_CLIENT) != NGX_OK) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } if (pscf->ssl_server_name || pscf->ssl_verify) { if (ngx_stream_proxy_ssl_name(s) != NGX_OK) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } } if (pscf->ssl_session_reuse) { if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } } @@ -1166,7 +1166,7 @@ ngx_stream_proxy_resolve_handler(ngx_res &ctx->name, ctx->state, ngx_resolver_strerror(ctx->state)); - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -1192,7 +1192,7 @@ ngx_stream_proxy_resolve_handler(ngx_res #endif if (ngx_stream_upstream_create_round_robin_peer(s, ur) != NGX_OK) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -1245,7 +1245,8 @@ ngx_stream_proxy_process_connection(ngx_ if (!ev->ready) { if (ngx_handle_read_event(ev, 0) != NGX_OK) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, + NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -1279,7 +1280,7 @@ ngx_stream_proxy_process_connection(ngx_ } ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); - ngx_stream_proxy_finalize(s, NGX_DECLINED); + ngx_stream_proxy_finalize(s, NGX_STREAM_OK); return; } @@ -1289,7 +1290,7 @@ ngx_stream_proxy_process_connection(ngx_ "stream connection delayed"); if (ngx_handle_read_event(ev, 0) != NGX_OK) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); } return; @@ -1407,7 +1408,7 @@ ngx_stream_proxy_process(ngx_stream_sess c->log->handler = handler; - ngx_stream_proxy_finalize(s, NGX_OK); + ngx_stream_proxy_finalize(s, NGX_STREAM_OK); return; } @@ -1449,7 +1450,7 @@ ngx_stream_proxy_process(ngx_stream_sess return; } - ngx_stream_proxy_finalize(s, NGX_DECLINED); + ngx_stream_proxy_finalize(s, NGX_STREAM_OK); return; } @@ -1540,20 +1541,20 @@ ngx_stream_proxy_process(ngx_stream_sess c->log->handler = handler; - ngx_stream_proxy_finalize(s, NGX_OK); + ngx_stream_proxy_finalize(s, NGX_STREAM_OK); return; } flags = src->read->eof ? NGX_CLOSE_EVENT : 0; if (!src->shared && ngx_handle_read_event(src->read, flags) != NGX_OK) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } if (dst) { if (!dst->shared && ngx_handle_write_event(dst->write, 0) != NGX_OK) { - ngx_stream_proxy_finalize(s, NGX_ERROR); + ngx_stream_proxy_finalize(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -1593,7 +1594,7 @@ ngx_stream_proxy_next_upstream(ngx_strea || !pscf->next_upstream || (timeout && ngx_current_msec - u->peer.start_time >= timeout)) { - ngx_stream_proxy_finalize(s, NGX_DECLINED); + ngx_stream_proxy_finalize(s, NGX_STREAM_BAD_GATEWAY); return; } @@ -1621,7 +1622,7 @@ ngx_stream_proxy_next_upstream(ngx_strea static void -ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_int_t rc) +ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_uint_t rc) { ngx_connection_t *pc; ngx_stream_upstream_t *u; @@ -1664,7 +1665,7 @@ ngx_stream_proxy_finalize(ngx_stream_ses noupstream: - ngx_stream_close_connection(s->connection); + ngx_stream_finalize_session(s, rc); } diff --git a/src/stream/ngx_stream_return_module.c b/src/stream/ngx_stream_return_module.c --- a/src/stream/ngx_stream_return_module.c +++ b/src/stream/ngx_stream_return_module.c @@ -83,7 +83,7 @@ ngx_stream_return_handler(ngx_stream_ses rscf = ngx_stream_get_module_srv_conf(s, ngx_stream_return_module); if (ngx_stream_complex_value(s, &rscf->text, &text) != NGX_OK) { - ngx_stream_close_connection(c); + ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -91,13 +91,13 @@ ngx_stream_return_handler(ngx_stream_ses "stream return text: \"%V\"", &text); if (text.len == 0) { - ngx_stream_close_connection(c); + ngx_stream_finalize_session(s, NGX_STREAM_OK); return; } ctx = ngx_pcalloc(c->pool, sizeof(ngx_stream_return_ctx_t)); if (ctx == NULL) { - ngx_stream_close_connection(c); + ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } @@ -126,7 +126,7 @@ ngx_stream_return_write_handler(ngx_even if (ev->timedout) { ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out"); - ngx_stream_close_connection(c); + ngx_stream_finalize_session(s, NGX_STREAM_OK); return; } @@ -137,7 +137,7 @@ ngx_stream_return_write_handler(ngx_even n = c->send(c, b->pos, b->last - b->pos); if (n == NGX_ERROR) { - ngx_stream_close_connection(c); + ngx_stream_finalize_session(s, NGX_STREAM_OK); return; } @@ -145,14 +145,14 @@ ngx_stream_return_write_handler(ngx_even b->pos += n; if (b->pos == b->last) { - ngx_stream_close_connection(c); + ngx_stream_finalize_session(s, NGX_STREAM_OK); return; } } } if (ngx_handle_write_event(ev, 0) != NGX_OK) { - ngx_stream_close_connection(c); + ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); return; } diff --git a/src/stream/ngx_stream_variables.c b/src/stream/ngx_stream_variables.c --- a/src/stream/ngx_stream_variables.c +++ b/src/stream/ngx_stream_variables.c @@ -25,6 +25,8 @@ static ngx_int_t ngx_stream_variable_byt ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_session_time(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_stream_variable_status(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_stream_variable_connection(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data); @@ -70,6 +72,9 @@ static ngx_stream_variable_t ngx_stream { ngx_string("session_time"), NULL, ngx_stream_variable_session_time, 0, NGX_STREAM_VAR_NOCACHEABLE, 0 }, + { ngx_string("status"), NULL, ngx_stream_variable_status, + 0, NGX_STREAM_VAR_NOCACHEABLE, 0 }, + { ngx_string("connection"), NULL, ngx_stream_variable_connection, 0, 0, 0 }, @@ -530,6 +535,24 @@ ngx_stream_variable_session_time(ngx_str static ngx_int_t +ngx_stream_variable_status(ngx_stream_session_t *s, + ngx_stream_variable_value_t *v, uintptr_t data) +{ + v->data = ngx_pnalloc(s->connection->pool, NGX_INT_T_LEN); + if (v->data == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(v->data, "%03ui", s->status) - v->data; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + + +static ngx_int_t ngx_stream_variable_connection(ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data) {