This commit is contained in:
Elijah Zupancic 2026-04-08 08:25:42 +00:00 committed by GitHub
commit f42a4ded4d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 77 additions and 28 deletions

View file

@ -1279,6 +1279,9 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
ctx->internal_body_length = -1;
ctx->internal_chunked = 1;
} else if (r->discard_body) {
ctx->internal_body_length = -1;
} else {
ctx->internal_body_length = r->headers_in.content_length_n;
}

View file

@ -2516,6 +2516,7 @@ ngx_http_subrequest(ngx_http_request_t *r,
sr->internal = 1;
sr->discard_body = r->discard_body;
sr->discarding_body = r->discarding_body;
sr->expect_tested = 1;
sr->main_filter_need_in_memory = r->main_filter_need_in_memory;

View file

@ -2019,6 +2019,15 @@ ngx_http_process_request_header(ngx_http_request_t *r)
}
if (r->headers_in.content_length) {
if (r->headers_in.transfer_encoding) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"client sent \"Content-Length\" and "
"\"Transfer-Encoding\" headers "
"at the same time");
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return NGX_ERROR;
}
r->headers_in.content_length_n =
ngx_atoof(r->headers_in.content_length->value.data,
r->headers_in.content_length->value.len);
@ -2044,15 +2053,6 @@ ngx_http_process_request_header(ngx_http_request_t *r)
&& ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
(u_char *) "chunked", 7) == 0)
{
if (r->headers_in.content_length) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"client sent \"Content-Length\" and "
"\"Transfer-Encoding\" headers "
"at the same time");
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
return NGX_ERROR;
}
r->headers_in.chunked = 1;
} else {
@ -2923,7 +2923,7 @@ ngx_http_finalize_connection(ngx_http_request_t *r)
if (r->main->count != 1) {
if (r->discard_body) {
if (r->discarding_body) {
r->read_event_handler = ngx_http_discarded_request_body_handler;
ngx_add_timer(r->connection->read, clcf->lingering_timeout);
@ -2988,7 +2988,7 @@ ngx_http_set_write_handler(ngx_http_request_t *r)
r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
r->read_event_handler = r->discard_body ?
r->read_event_handler = r->discarding_body ?
ngx_http_discarded_request_body_handler:
ngx_http_test_reading;
r->write_event_handler = ngx_http_writer;

View file

@ -310,6 +310,7 @@ typedef struct {
ngx_chain_t *busy;
ngx_http_chunked_t *chunked;
ngx_http_client_body_handler_pt post_handler;
unsigned no_buffering:1;
unsigned filter_need_buffering:1;
unsigned last_sent:1;
unsigned last_saved:1;
@ -546,6 +547,7 @@ struct ngx_http_request_s {
unsigned keepalive:1;
unsigned lingering_close:1;
unsigned discard_body:1;
unsigned discarding_body:1;
unsigned reading_body:1;
unsigned internal:1;
unsigned error_page:1;

View file

@ -44,6 +44,18 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
if (r != r->main || r->request_body || r->discard_body) {
r->request_body_no_buffering = 0;
if (r->request_body && r->request_body->no_buffering) {
r->discard_body = 1;
r->request_body->bufs = NULL;
if (r->reading_body) {
r->reading_body = 0;
r->keepalive = 0;
r->lingering_close = 1;
}
}
post_handler(r);
return NGX_OK;
}
@ -69,6 +81,7 @@ ngx_http_read_client_request_body(ngx_http_request_t *r,
* rb->busy = NULL;
* rb->chunked = NULL;
* rb->received = 0;
* rb->no_buffering = 0;
* rb->filter_need_buffering = 0;
* rb->last_sent = 0;
* rb->last_saved = 0;
@ -214,6 +227,7 @@ done:
} else {
/* rc == NGX_AGAIN */
r->reading_body = 1;
r->request_body->no_buffering = 1;
}
r->read_event_handler = ngx_http_block_reading;
@ -221,7 +235,16 @@ done:
}
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
r->lingering_close = 1;
r->discard_body = 1;
if (r->request_body) {
r->request_body->bufs = NULL;
}
r->main->count--;
r->read_event_handler = ngx_http_block_reading;
}
return rc;
@ -286,6 +309,12 @@ ngx_http_read_client_request_body_handler(ngx_http_request_t *r)
rc = ngx_http_do_read_client_request_body(r);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
r->lingering_close = 1;
r->discard_body = 1;
r->request_body->bufs = NULL;
r->read_event_handler = ngx_http_block_reading;
ngx_http_finalize_request(r, rc);
}
}
@ -637,6 +666,11 @@ ngx_http_discard_request_body(ngx_http_request_t *r)
return NGX_OK;
}
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http set discard body");
r->discard_body = 1;
#if (NGX_HTTP_V2)
if (r->stream) {
r->stream->skip_data = 1;
@ -656,8 +690,6 @@ ngx_http_discard_request_body(ngx_http_request_t *r)
rev = r->connection->read;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body");
if (rev->timer_set) {
ngx_del_timer(rev);
}
@ -700,7 +732,7 @@ ngx_http_discard_request_body(ngx_http_request_t *r)
}
r->count++;
r->discard_body = 1;
r->discarding_body = 1;
return NGX_OK;
}
@ -729,7 +761,7 @@ ngx_http_discarded_request_body_handler(ngx_http_request_t *r)
timer = (ngx_msec_t) r->lingering_time - (ngx_msec_t) ngx_time();
if ((ngx_msec_int_t) timer <= 0) {
r->discard_body = 0;
r->discarding_body = 0;
r->lingering_close = 0;
ngx_http_finalize_request(r, NGX_ERROR);
return;
@ -742,7 +774,7 @@ ngx_http_discarded_request_body_handler(ngx_http_request_t *r)
rc = ngx_http_read_discarded_request_body(r);
if (rc == NGX_OK) {
r->discard_body = 0;
r->discarding_body = 0;
r->lingering_close = 0;
r->lingering_time = 0;
ngx_http_finalize_request(r, NGX_DONE);
@ -1149,8 +1181,6 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
r->headers_in.content_length_n,
rb->chunked->size);
r->lingering_close = 1;
return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
}

View file

@ -1194,17 +1194,20 @@ ngx_http_variable_content_length(ngx_http_request_t *r,
{
u_char *p;
if (r->headers_in.content_length) {
if (r->reading_body && r->headers_in.content_length) {
v->len = r->headers_in.content_length->value.len;
v->data = r->headers_in.content_length->value.data;
v->valid = 1;
v->no_cacheable = 0;
v->no_cacheable = 1;
v->not_found = 0;
} else if (r->reading_body) {
v->not_found = 1;
v->no_cacheable = 1;
} else if (r->discard_body) {
v->not_found = 1;
} else if (r->headers_in.content_length_n >= 0) {
p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
if (p == NULL) {
@ -1214,7 +1217,7 @@ ngx_http_variable_content_length(ngx_http_request_t *r,
v->len = ngx_sprintf(p, "%O", r->headers_in.content_length_n) - p;
v->data = p;
v->valid = 1;
v->no_cacheable = 0;
v->no_cacheable = 1;
v->not_found = 0;
} else if (r->headers_in.chunked) {

View file

@ -1084,13 +1084,6 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
r = stream->request;
fc = r->connection;
if (r->reading_body && !r->request_body_no_buffering) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
"skipping http2 DATA frame");
return ngx_http_v2_state_skip_padded(h2c, pos, end);
}
if (r->headers_in.content_length_n < 0 && !r->headers_in.chunked) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
"skipping http2 DATA frame");
@ -1112,7 +1105,11 @@ ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
stream->in_closed, 0);
if (rc != NGX_OK && rc != NGX_AGAIN) {
stream->skip_data = 1;
r->discard_body = 1;
r->request_body->bufs = NULL;
ngx_http_finalize_request(r, rc);
}
@ -3871,6 +3868,7 @@ ngx_http_v2_run_request(ngx_http_request_t *r)
"client prematurely closed stream");
r->stream->skip_data = 1;
r->discard_body = 1;
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
goto failed;
@ -4312,6 +4310,8 @@ ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r)
if (rc != NGX_OK && rc != NGX_AGAIN) {
r->stream->skip_data = 1;
r->discard_body = 1;
r->request_body->bufs = NULL;
ngx_http_finalize_request(r, rc);
return;
}
@ -4352,6 +4352,8 @@ ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r)
"http2 negative window update");
stream->skip_data = 1;
r->discard_body = 1;
r->request_body->bufs = NULL;
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
@ -4365,6 +4367,8 @@ ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r)
== NGX_ERROR)
{
stream->skip_data = 1;
r->discard_body = 1;
r->request_body->bufs = NULL;
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
@ -4373,6 +4377,8 @@ ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r)
if (ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) {
stream->skip_data = 1;
r->discard_body = 1;
r->request_body->bufs = NULL;
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}

View file

@ -1310,6 +1310,10 @@ ngx_http_v3_read_client_request_body_handler(ngx_http_request_t *r)
rc = ngx_http_v3_do_read_client_request_body(r);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
r->discard_body = 1;
r->request_body->bufs = NULL;
ngx_http_finalize_request(r, rc);
}
}