Latest update - 7680
This commit is contained in:
@@ -960,6 +960,22 @@ ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (p->upstream_done) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
|
||||
"input data after close");
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (p->length == 0) {
|
||||
p->upstream_done = 1;
|
||||
|
||||
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||
"upstream sent more data than specified in "
|
||||
"\"Content-Length\" header");
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
cl = ngx_chain_get_free_buf(p->pool, &p->free);
|
||||
if (cl == NULL) {
|
||||
return NGX_ERROR;
|
||||
@@ -987,6 +1003,18 @@ ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (b->last - b->pos > p->length) {
|
||||
|
||||
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||
"upstream sent more data than specified in "
|
||||
"\"Content-Length\" header");
|
||||
|
||||
b->last = b->pos + p->length;
|
||||
p->upstream_done = 1;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
p->length -= b->last - b->pos;
|
||||
|
||||
return NGX_OK;
|
||||
|
||||
@@ -81,12 +81,15 @@ typedef struct {
|
||||
size_t length;
|
||||
size_t padding;
|
||||
|
||||
off_t rest;
|
||||
|
||||
ngx_chain_t *free;
|
||||
ngx_chain_t *busy;
|
||||
|
||||
unsigned fastcgi_stdout:1;
|
||||
unsigned large_stderr:1;
|
||||
unsigned header_sent:1;
|
||||
unsigned closed:1;
|
||||
|
||||
ngx_array_t *split_parts;
|
||||
|
||||
@@ -2075,13 +2078,31 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r)
|
||||
static ngx_int_t
|
||||
ngx_http_fastcgi_input_filter_init(void *data)
|
||||
{
|
||||
ngx_http_request_t *r = data;
|
||||
ngx_http_request_t *r = data;
|
||||
|
||||
ngx_http_upstream_t *u;
|
||||
ngx_http_fastcgi_ctx_t *f;
|
||||
ngx_http_fastcgi_loc_conf_t *flcf;
|
||||
|
||||
u = r->upstream;
|
||||
|
||||
f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
|
||||
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
|
||||
|
||||
r->upstream->pipe->length = flcf->keep_conn ?
|
||||
(off_t) sizeof(ngx_http_fastcgi_header_t) : -1;
|
||||
u->pipe->length = flcf->keep_conn ?
|
||||
(off_t) sizeof(ngx_http_fastcgi_header_t) : -1;
|
||||
|
||||
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|
||||
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
|
||||
{
|
||||
f->rest = 0;
|
||||
|
||||
} else if (r->method == NGX_HTTP_HEAD) {
|
||||
f->rest = -2;
|
||||
|
||||
} else {
|
||||
f->rest = u->headers_in.content_length_n;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
@@ -2106,6 +2127,15 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
||||
f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
|
||||
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
|
||||
|
||||
if (p->upstream_done || f->closed) {
|
||||
r->upstream->keepalive = 0;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
||||
"http fastcgi data after close");
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
b = NULL;
|
||||
prev = &buf->shadow;
|
||||
|
||||
@@ -2128,13 +2158,25 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
||||
if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
|
||||
f->state = ngx_http_fastcgi_st_padding;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
||||
"http fastcgi closed stdout");
|
||||
|
||||
if (f->rest > 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, p->log, 0,
|
||||
"upstream prematurely closed "
|
||||
"FastCGI stdout");
|
||||
|
||||
p->upstream_error = 1;
|
||||
p->upstream_eof = 0;
|
||||
f->closed = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!flcf->keep_conn) {
|
||||
p->upstream_done = 1;
|
||||
}
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
||||
"http fastcgi closed stdout");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2143,6 +2185,18 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
||||
"http fastcgi sent end request");
|
||||
|
||||
if (f->rest > 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, p->log, 0,
|
||||
"upstream prematurely closed "
|
||||
"FastCGI request");
|
||||
|
||||
p->upstream_error = 1;
|
||||
p->upstream_eof = 0;
|
||||
f->closed = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!flcf->keep_conn) {
|
||||
p->upstream_done = 1;
|
||||
break;
|
||||
@@ -2289,15 +2343,31 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
||||
f->pos += f->length;
|
||||
b->last = f->pos;
|
||||
|
||||
continue;
|
||||
} else {
|
||||
f->length -= f->last - f->pos;
|
||||
f->pos = f->last;
|
||||
b->last = f->last;
|
||||
}
|
||||
|
||||
f->length -= f->last - f->pos;
|
||||
if (f->rest == -2) {
|
||||
f->rest = r->upstream->headers_in.content_length_n;
|
||||
}
|
||||
|
||||
b->last = f->last;
|
||||
if (f->rest >= 0) {
|
||||
|
||||
break;
|
||||
if (b->last - b->pos > f->rest) {
|
||||
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||
"upstream sent more data than specified in "
|
||||
"\"Content-Length\" header");
|
||||
|
||||
b->last = b->pos + f->rest;
|
||||
p->upstream_done = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
f->rest -= b->last - b->pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (flcf->keep_conn) {
|
||||
@@ -2391,6 +2461,14 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
|
||||
|
||||
if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
|
||||
|
||||
if (f->rest > 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream prematurely closed "
|
||||
"FastCGI request");
|
||||
u->error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (f->pos + f->padding < f->last) {
|
||||
u->length = 0;
|
||||
break;
|
||||
@@ -2510,13 +2588,27 @@ ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
|
||||
f->pos += f->length;
|
||||
b->last = f->pos;
|
||||
|
||||
continue;
|
||||
} else {
|
||||
f->length -= f->last - f->pos;
|
||||
f->pos = f->last;
|
||||
b->last = f->last;
|
||||
}
|
||||
|
||||
f->length -= f->last - f->pos;
|
||||
b->last = f->last;
|
||||
if (f->rest >= 0) {
|
||||
|
||||
break;
|
||||
if (b->last - b->pos > f->rest) {
|
||||
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||
"upstream sent more data than specified in "
|
||||
"\"Content-Length\" header");
|
||||
|
||||
b->last = b->pos + f->rest;
|
||||
u->length = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
f->rest -= b->last - b->pos;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
|
||||
@@ -84,6 +84,8 @@ typedef struct {
|
||||
ngx_uint_t pings;
|
||||
ngx_uint_t settings;
|
||||
|
||||
off_t length;
|
||||
|
||||
ssize_t send_window;
|
||||
size_t recv_window;
|
||||
|
||||
@@ -1953,10 +1955,28 @@ ngx_http_grpc_filter_init(void *data)
|
||||
r = ctx->request;
|
||||
u = r->upstream;
|
||||
|
||||
u->length = 1;
|
||||
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|
||||
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
|
||||
|| r->method == NGX_HTTP_HEAD)
|
||||
{
|
||||
ctx->length = 0;
|
||||
|
||||
} else {
|
||||
ctx->length = u->headers_in.content_length_n;
|
||||
}
|
||||
|
||||
if (ctx->end_stream) {
|
||||
|
||||
if (ctx->length > 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream prematurely closed stream");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
u->length = 0;
|
||||
|
||||
} else {
|
||||
u->length = 1;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
@@ -1999,6 +2019,12 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
|
||||
|
||||
if (ctx->done) {
|
||||
|
||||
if (ctx->length > 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream prematurely closed stream");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have finished parsing the response and the
|
||||
* remaining control frames. If there are unsent
|
||||
@@ -2052,6 +2078,17 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ctx->length != -1) {
|
||||
if ((off_t) ctx->rest > ctx->length) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent response body larger "
|
||||
"than indicated content length");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ctx->length -= ctx->rest;
|
||||
}
|
||||
|
||||
if (ctx->rest > ctx->recv_window) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream violated stream flow control, "
|
||||
|
||||
@@ -485,10 +485,11 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
|
||||
|
||||
if (u->length == (ssize_t) ctx->rest) {
|
||||
|
||||
if (ngx_strncmp(b->last,
|
||||
if (bytes > u->length
|
||||
|| ngx_strncmp(b->last,
|
||||
ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END - ctx->rest,
|
||||
bytes)
|
||||
!= 0)
|
||||
!= 0)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
|
||||
"memcached sent invalid trailer");
|
||||
@@ -540,7 +541,9 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
|
||||
|
||||
last += (size_t) (u->length - NGX_HTTP_MEMCACHED_END);
|
||||
|
||||
if (ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0) {
|
||||
if (bytes > u->length
|
||||
|| ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
|
||||
"memcached sent invalid trailer");
|
||||
|
||||
|
||||
@@ -2015,6 +2015,25 @@ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (p->upstream_done) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
||||
"http proxy data after close");
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (p->length == 0) {
|
||||
|
||||
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||
"upstream sent more data than specified in "
|
||||
"\"Content-Length\" header");
|
||||
|
||||
r = p->input_ctx;
|
||||
r->upstream->keepalive = 0;
|
||||
p->upstream_done = 1;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
cl = ngx_chain_get_free_buf(p->pool, &p->free);
|
||||
if (cl == NULL) {
|
||||
return NGX_ERROR;
|
||||
@@ -2042,20 +2061,23 @@ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (b->last - b->pos > p->length) {
|
||||
|
||||
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||
"upstream sent more data than specified in "
|
||||
"\"Content-Length\" header");
|
||||
|
||||
b->last = b->pos + p->length;
|
||||
p->upstream_done = 1;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
p->length -= b->last - b->pos;
|
||||
|
||||
if (p->length == 0) {
|
||||
r = p->input_ctx;
|
||||
p->upstream_done = 1;
|
||||
r->upstream->keepalive = !r->upstream->headers_in.connection_close;
|
||||
|
||||
} else if (p->length < 0) {
|
||||
r = p->input_ctx;
|
||||
p->upstream_done = 1;
|
||||
|
||||
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||
"upstream sent more data than specified in "
|
||||
"\"Content-Length\" header");
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
@@ -2082,6 +2104,23 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (p->upstream_done) {
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
||||
"http proxy data after close");
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (p->length == 0) {
|
||||
|
||||
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||
"upstream sent data after final chunk");
|
||||
|
||||
r->upstream->keepalive = 0;
|
||||
p->upstream_done = 1;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
b = NULL;
|
||||
prev = &buf->shadow;
|
||||
|
||||
@@ -2144,9 +2183,15 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
||||
|
||||
/* a whole response has been parsed successfully */
|
||||
|
||||
p->upstream_done = 1;
|
||||
p->length = 0;
|
||||
r->upstream->keepalive = !r->upstream->headers_in.connection_close;
|
||||
|
||||
if (buf->pos != buf->last) {
|
||||
ngx_log_error(NGX_LOG_WARN, p->log, 0,
|
||||
"upstream sent data after final chunk");
|
||||
r->upstream->keepalive = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2161,13 +2206,13 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
|
||||
|
||||
/* invalid response */
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
ngx_log_error(NGX_LOG_ERR, p->log, 0,
|
||||
"upstream sent invalid chunked response");
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, p->log, 0,
|
||||
"http proxy chunked state %ui, length %O",
|
||||
ctx->chunked.state, p->length);
|
||||
|
||||
@@ -2227,6 +2272,18 @@ ngx_http_proxy_non_buffered_copy_filter(void *data, ssize_t bytes)
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (bytes > u->length) {
|
||||
|
||||
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||
"upstream sent more data than specified in "
|
||||
"\"Content-Length\" header");
|
||||
|
||||
cl->buf->last = cl->buf->pos + u->length;
|
||||
u->length = 0;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
u->length -= bytes;
|
||||
|
||||
if (u->length == 0) {
|
||||
@@ -2313,6 +2370,12 @@ ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
|
||||
u->keepalive = !u->headers_in.connection_close;
|
||||
u->length = 0;
|
||||
|
||||
if (buf->pos != buf->last) {
|
||||
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||
"upstream sent data after final chunk");
|
||||
u->keepalive = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ static ngx_int_t ngx_http_scgi_create_request(ngx_http_request_t *r);
|
||||
static ngx_int_t ngx_http_scgi_reinit_request(ngx_http_request_t *r);
|
||||
static ngx_int_t ngx_http_scgi_process_status_line(ngx_http_request_t *r);
|
||||
static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r);
|
||||
static ngx_int_t ngx_http_scgi_input_filter_init(void *data);
|
||||
static void ngx_http_scgi_abort_request(ngx_http_request_t *r);
|
||||
static void ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
|
||||
|
||||
@@ -534,6 +535,10 @@ ngx_http_scgi_handler(ngx_http_request_t *r)
|
||||
u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
|
||||
u->pipe->input_ctx = r;
|
||||
|
||||
u->input_filter_init = ngx_http_scgi_input_filter_init;
|
||||
u->input_filter = ngx_http_upstream_non_buffered_filter;
|
||||
u->input_filter_ctx = r;
|
||||
|
||||
if (!scf->upstream.request_buffering
|
||||
&& scf->upstream.pass_request_body
|
||||
&& !r->headers_in.chunked)
|
||||
@@ -1145,6 +1150,37 @@ ngx_http_scgi_process_header(ngx_http_request_t *r)
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_scgi_input_filter_init(void *data)
|
||||
{
|
||||
ngx_http_request_t *r = data;
|
||||
ngx_http_upstream_t *u;
|
||||
|
||||
u = r->upstream;
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http scgi filter init s:%ui l:%O",
|
||||
u->headers_in.status_n, u->headers_in.content_length_n);
|
||||
|
||||
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|
||||
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
|
||||
{
|
||||
u->pipe->length = 0;
|
||||
u->length = 0;
|
||||
|
||||
} else if (r->method == NGX_HTTP_HEAD) {
|
||||
u->pipe->length = -1;
|
||||
u->length = -1;
|
||||
|
||||
} else {
|
||||
u->pipe->length = u->headers_in.content_length_n;
|
||||
u->length = u->headers_in.content_length_n;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_scgi_abort_request(ngx_http_request_t *r)
|
||||
{
|
||||
|
||||
@@ -67,6 +67,7 @@ static ngx_int_t ngx_http_uwsgi_create_request(ngx_http_request_t *r);
|
||||
static ngx_int_t ngx_http_uwsgi_reinit_request(ngx_http_request_t *r);
|
||||
static ngx_int_t ngx_http_uwsgi_process_status_line(ngx_http_request_t *r);
|
||||
static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r);
|
||||
static ngx_int_t ngx_http_uwsgi_input_filter_init(void *data);
|
||||
static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r);
|
||||
static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r,
|
||||
ngx_int_t rc);
|
||||
@@ -703,6 +704,10 @@ ngx_http_uwsgi_handler(ngx_http_request_t *r)
|
||||
u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
|
||||
u->pipe->input_ctx = r;
|
||||
|
||||
u->input_filter_init = ngx_http_uwsgi_input_filter_init;
|
||||
u->input_filter = ngx_http_upstream_non_buffered_filter;
|
||||
u->input_filter_ctx = r;
|
||||
|
||||
if (!uwcf->upstream.request_buffering
|
||||
&& uwcf->upstream.pass_request_body
|
||||
&& !r->headers_in.chunked)
|
||||
@@ -1356,6 +1361,37 @@ ngx_http_uwsgi_process_header(ngx_http_request_t *r)
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_uwsgi_input_filter_init(void *data)
|
||||
{
|
||||
ngx_http_request_t *r = data;
|
||||
ngx_http_upstream_t *u;
|
||||
|
||||
u = r->upstream;
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http uwsgi filter init s:%ui l:%O",
|
||||
u->headers_in.status_n, u->headers_in.content_length_n);
|
||||
|
||||
if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
|
||||
|| u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED)
|
||||
{
|
||||
u->pipe->length = 0;
|
||||
u->length = 0;
|
||||
|
||||
} else if (r->method == NGX_HTTP_HEAD) {
|
||||
u->pipe->length = -1;
|
||||
u->length = -1;
|
||||
|
||||
} else {
|
||||
u->pipe->length = u->headers_in.content_length_n;
|
||||
u->length = u->headers_in.content_length_n;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_uwsgi_abort_request(ngx_http_request_t *r)
|
||||
{
|
||||
|
||||
@@ -77,9 +77,6 @@ static void
|
||||
static void
|
||||
ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
|
||||
ngx_uint_t do_write);
|
||||
static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
|
||||
static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data,
|
||||
ssize_t bytes);
|
||||
#if (NGX_THREADS)
|
||||
static ngx_int_t ngx_http_upstream_thread_handler(ngx_thread_task_t *task,
|
||||
ngx_file_t *file);
|
||||
@@ -1919,6 +1916,7 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
|
||||
u->keepalive = 0;
|
||||
u->upgrade = 0;
|
||||
u->error = 0;
|
||||
|
||||
ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
|
||||
u->headers_in.content_length_n = -1;
|
||||
@@ -3627,7 +3625,7 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
|
||||
return;
|
||||
}
|
||||
|
||||
if (upstream->read->error) {
|
||||
if (upstream->read->error || u->error) {
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
NGX_HTTP_BAD_GATEWAY);
|
||||
return;
|
||||
@@ -3705,14 +3703,14 @@ ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_int_t
|
||||
ngx_http_upstream_non_buffered_filter_init(void *data)
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_int_t
|
||||
ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
|
||||
{
|
||||
ngx_http_request_t *r = data;
|
||||
@@ -3748,6 +3746,18 @@ ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (bytes > u->length) {
|
||||
|
||||
ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
|
||||
"upstream sent more data than specified in "
|
||||
"\"Content-Length\" header");
|
||||
|
||||
cl->buf->last = cl->buf->pos + u->length;
|
||||
u->length = 0;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
u->length -= bytes;
|
||||
|
||||
return NGX_OK;
|
||||
|
||||
@@ -391,6 +391,7 @@ struct ngx_http_upstream_s {
|
||||
unsigned buffering:1;
|
||||
unsigned keepalive:1;
|
||||
unsigned upgrade:1;
|
||||
unsigned error:1;
|
||||
|
||||
unsigned request_sent:1;
|
||||
unsigned request_body_sent:1;
|
||||
@@ -414,6 +415,8 @@ typedef struct {
|
||||
|
||||
ngx_int_t ngx_http_upstream_create(ngx_http_request_t *r);
|
||||
void ngx_http_upstream_init(ngx_http_request_t *r);
|
||||
ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
|
||||
ngx_int_t ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes);
|
||||
ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf,
|
||||
ngx_url_t *u, ngx_uint_t flags);
|
||||
char *ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
|
||||
+122
-6
@@ -60,6 +60,8 @@ typedef struct {
|
||||
static void ngx_http_v2_read_handler(ngx_event_t *rev);
|
||||
static void ngx_http_v2_write_handler(ngx_event_t *wev);
|
||||
static void ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c);
|
||||
static void ngx_http_v2_lingering_close(ngx_http_v2_connection_t *h2c);
|
||||
static void ngx_http_v2_lingering_close_handler(ngx_event_t *rev);
|
||||
|
||||
static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c,
|
||||
u_char *pos, u_char *end);
|
||||
@@ -663,7 +665,7 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
|
||||
}
|
||||
|
||||
if (h2c->goaway) {
|
||||
ngx_http_close_connection(c);
|
||||
ngx_http_v2_lingering_close(h2c);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -701,6 +703,113 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_v2_lingering_close(ngx_http_v2_connection_t *h2c)
|
||||
{
|
||||
ngx_event_t *rev, *wev;
|
||||
ngx_connection_t *c;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
|
||||
c = h2c->connection;
|
||||
|
||||
clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx,
|
||||
ngx_http_core_module);
|
||||
|
||||
if (clcf->lingering_close == NGX_HTTP_LINGERING_OFF) {
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
rev = c->read;
|
||||
rev->handler = ngx_http_v2_lingering_close_handler;
|
||||
|
||||
h2c->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
|
||||
ngx_add_timer(rev, clcf->lingering_timeout);
|
||||
|
||||
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
wev = c->write;
|
||||
wev->handler = ngx_http_empty_handler;
|
||||
|
||||
if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
|
||||
if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
|
||||
ngx_connection_error(c, ngx_socket_errno,
|
||||
ngx_shutdown_socket_n " failed");
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rev->ready) {
|
||||
ngx_http_v2_lingering_close_handler(rev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_v2_lingering_close_handler(ngx_event_t *rev)
|
||||
{
|
||||
ssize_t n;
|
||||
ngx_msec_t timer;
|
||||
ngx_connection_t *c;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
ngx_http_v2_connection_t *h2c;
|
||||
u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
|
||||
|
||||
c = rev->data;
|
||||
h2c = c->data;
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http2 lingering close handler");
|
||||
|
||||
if (rev->timedout) {
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
timer = (ngx_msec_t) h2c->lingering_time - (ngx_msec_t) ngx_time();
|
||||
if ((ngx_msec_int_t) timer <= 0) {
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %z", n);
|
||||
|
||||
if (n == NGX_ERROR || n == 0) {
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
} while (rev->ready);
|
||||
|
||||
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
clcf = ngx_http_get_module_loc_conf(h2c->http_connection->conf_ctx,
|
||||
ngx_http_core_module);
|
||||
timer *= 1000;
|
||||
|
||||
if (timer > clcf->lingering_timeout) {
|
||||
timer = clcf->lingering_timeout;
|
||||
}
|
||||
|
||||
ngx_add_timer(rev, timer);
|
||||
}
|
||||
|
||||
|
||||
static u_char *
|
||||
ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos,
|
||||
u_char *end)
|
||||
@@ -4551,16 +4660,15 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
|
||||
h2c->blocked = 1;
|
||||
|
||||
if (!c->error && !h2c->goaway) {
|
||||
h2c->goaway = 1;
|
||||
|
||||
if (ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) {
|
||||
(void) ngx_http_v2_send_output_queue(h2c);
|
||||
}
|
||||
}
|
||||
|
||||
c->error = 1;
|
||||
|
||||
if (!h2c->processing && !h2c->pushing) {
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
|
||||
c->read->handler = ngx_http_empty_handler;
|
||||
@@ -4608,10 +4716,18 @@ ngx_http_v2_finalize_connection(ngx_http_v2_connection_t *h2c,
|
||||
h2c->blocked = 0;
|
||||
|
||||
if (h2c->processing || h2c->pushing) {
|
||||
c->error = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_http_close_connection(c);
|
||||
done:
|
||||
|
||||
if (c->error) {
|
||||
ngx_http_close_connection(c);
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_http_v2_lingering_close(h2c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -207,6 +207,8 @@ struct ngx_http_v2_connection_s {
|
||||
ngx_uint_t last_sid;
|
||||
ngx_uint_t last_push;
|
||||
|
||||
time_t lingering_time;
|
||||
|
||||
unsigned closed_nodes:8;
|
||||
unsigned settings_ack:1;
|
||||
unsigned table_update:1;
|
||||
|
||||
Reference in New Issue
Block a user