diff options
| author | Maxim Dounin <mdounin@mdounin.ru> | 2013-07-25 15:00:12 +0400 |
|---|---|---|
| committer | Maxim Dounin <mdounin@mdounin.ru> | 2013-07-25 15:00:12 +0400 |
| commit | 960d0bfe344d70223fec74079378992897855cc3 (patch) | |
| tree | 693f16dba087ac7a7a97fca2015d9aae7c621170 | |
| parent | 416b922bd2c285551d195c1f33a3736775ea45e9 (diff) | |
| download | nginx-960d0bfe344d70223fec74079378992897855cc3.tar.gz nginx-960d0bfe344d70223fec74079378992897855cc3.tar.bz2 | |
Upstream: added check if a response is complete.
Checks were added to both buffered and unbuffered code paths to detect
and complain if a response is incomplete. Appropriate error codes are
now passed to ngx_http_upstream_finalize_request().
With this change in unbuffered mode we now use u->length set to -1 as an
indicator that EOF is allowed per protocol and used to indicate response
end (much like its with p->length in buffered mode). Proxy module was
changed to set u->length to 1 (instead of previously used -1) in case of
chunked transfer encoding used to comply with the above.
| -rw-r--r-- | src/http/modules/ngx_http_proxy_module.c | 2 | ||||
| -rw-r--r-- | src/http/ngx_http_upstream.c | 33 |
2 files changed, 31 insertions, 4 deletions
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index 2cf0133a3..a22ed0fcb 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -1542,7 +1542,7 @@ ngx_http_proxy_input_filter_init(void *data) u->pipe->length = 3; /* "0" LF LF */ u->input_filter = ngx_http_proxy_non_buffered_chunked_filter; - u->length = -1; + u->length = 1; } else if (u->headers_in.content_length_n == 0) { /* empty body: special case as filter won't be called */ diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 8781fdca4..c4e0c645c 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -2748,13 +2748,27 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r, if (u->busy_bufs == NULL) { if (u->length == 0 - || upstream->read->eof - || upstream->read->error) + || (upstream->read->eof && u->length == -1)) { ngx_http_upstream_finalize_request(r, u, 0); return; } + if (upstream->read->eof) { + ngx_log_error(NGX_LOG_ERR, upstream->log, 0, + "upstream prematurely closed connection"); + + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_BAD_GATEWAY); + return; + } + + if (upstream->read->error) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_BAD_GATEWAY); + return; + } + b->pos = b->start; b->last = b->start; } @@ -3027,7 +3041,20 @@ ngx_http_upstream_process_request(ngx_http_request_t *r) if (p->upstream_done || p->upstream_eof || p->upstream_error) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http upstream exit: %p", p->out); - ngx_http_upstream_finalize_request(r, u, 0); + + if (p->upstream_done + || (p->upstream_eof && p->length == -1)) + { + ngx_http_upstream_finalize_request(r, u, 0); + return; + } + + if (p->upstream_eof) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "upstream prematurely closed connection"); + } + + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY); return; } } |
