Mercurial > hg > nginx
comparison src/http/v2/ngx_http_v2.c @ 7923:4775c1d27378
HTTP/2: fixed timers left after request body reading.
Following rb->filter_need_buffering changes, request body reading is
only finished after the filter chain is called and rb->last_saved is set.
As such, with r->request_body_no_buffering, timer on fc->read is no
longer removed when the last part of the body is received, potentially
resulting in incorrect behaviour.
The fix is to call ngx_http_v2_process_request_body() from the
ngx_http_v2_read_unbuffered_request_body() function instead of
directly calling ngx_http_v2_filter_request_body(), so the timer
is properly removed.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 06 Sep 2021 14:54:48 +0300 |
parents | e9f402bfe37e |
children | d9e009b39596 |
comparison
equal
deleted
inserted
replaced
7922:e9f402bfe37e | 7923:4775c1d27378 |
---|---|
4261 | 4261 |
4262 if (size == 0 && last) { | 4262 if (size == 0 && last) { |
4263 rb->rest = 0; | 4263 rb->rest = 0; |
4264 } | 4264 } |
4265 | 4265 |
4266 if (r->request_body_no_buffering) { | 4266 if (r->request_body_no_buffering && !flush) { |
4267 break; | 4267 break; |
4268 } | 4268 } |
4269 | 4269 |
4270 /* pass buffer to request body filter chain */ | 4270 /* pass buffer to request body filter chain */ |
4271 | 4271 |
4294 if (size == 0) { | 4294 if (size == 0) { |
4295 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 4295 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
4296 ngx_add_timer(fc->read, clcf->client_body_timeout); | 4296 ngx_add_timer(fc->read, clcf->client_body_timeout); |
4297 | 4297 |
4298 if (r->request_body_no_buffering) { | 4298 if (r->request_body_no_buffering) { |
4299 ngx_post_event(fc->read, &ngx_posted_events); | 4299 if (!flush) { |
4300 ngx_post_event(fc->read, &ngx_posted_events); | |
4301 } | |
4302 | |
4300 return NGX_AGAIN; | 4303 return NGX_AGAIN; |
4301 } | 4304 } |
4302 | 4305 |
4303 return NGX_AGAIN; | 4306 return NGX_AGAIN; |
4304 } | 4307 } |
4307 if (fc->read->timer_set) { | 4310 if (fc->read->timer_set) { |
4308 ngx_del_timer(fc->read); | 4311 ngx_del_timer(fc->read); |
4309 } | 4312 } |
4310 | 4313 |
4311 if (r->request_body_no_buffering) { | 4314 if (r->request_body_no_buffering) { |
4312 ngx_post_event(fc->read, &ngx_posted_events); | 4315 if (!flush) { |
4316 ngx_post_event(fc->read, &ngx_posted_events); | |
4317 } | |
4318 | |
4313 return NGX_OK; | 4319 return NGX_OK; |
4314 } | 4320 } |
4315 | 4321 |
4316 if (r->headers_in.chunked) { | 4322 if (r->headers_in.chunked) { |
4317 r->headers_in.content_length_n = rb->received; | 4323 r->headers_in.content_length_n = rb->received; |
4525 ngx_buf_t *buf; | 4531 ngx_buf_t *buf; |
4526 ngx_int_t rc; | 4532 ngx_int_t rc; |
4527 ngx_connection_t *fc; | 4533 ngx_connection_t *fc; |
4528 ngx_http_v2_stream_t *stream; | 4534 ngx_http_v2_stream_t *stream; |
4529 ngx_http_v2_connection_t *h2c; | 4535 ngx_http_v2_connection_t *h2c; |
4530 ngx_http_core_loc_conf_t *clcf; | |
4531 | 4536 |
4532 stream = r->stream; | 4537 stream = r->stream; |
4533 fc = r->connection; | 4538 fc = r->connection; |
4534 | 4539 |
4535 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, | 4540 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, |
4549 if (fc->error) { | 4554 if (fc->error) { |
4550 stream->skip_data = 1; | 4555 stream->skip_data = 1; |
4551 return NGX_HTTP_BAD_REQUEST; | 4556 return NGX_HTTP_BAD_REQUEST; |
4552 } | 4557 } |
4553 | 4558 |
4554 rc = ngx_http_v2_filter_request_body(r); | 4559 rc = ngx_http_v2_process_request_body(r, NULL, 0, r->stream->in_closed, 1); |
4555 | 4560 |
4556 if (rc != NGX_OK) { | 4561 if (rc != NGX_OK && rc != NGX_AGAIN) { |
4557 stream->skip_data = 1; | 4562 stream->skip_data = 1; |
4558 return rc; | 4563 return rc; |
4559 } | 4564 } |
4560 | 4565 |
4561 if (r->request_body->rest == 0 && r->request_body->last_saved) { | 4566 if (rc == NGX_OK) { |
4562 return NGX_OK; | 4567 return NGX_OK; |
4563 } | 4568 } |
4564 | 4569 |
4565 if (r->request_body->rest == 0) { | 4570 if (r->request_body->rest == 0) { |
4566 return NGX_AGAIN; | 4571 return NGX_AGAIN; |
4602 } | 4607 } |
4603 | 4608 |
4604 if (ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) { | 4609 if (ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) { |
4605 stream->skip_data = 1; | 4610 stream->skip_data = 1; |
4606 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 4611 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
4607 } | |
4608 | |
4609 if (stream->recv_window == 0) { | |
4610 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
4611 ngx_add_timer(fc->read, clcf->client_body_timeout); | |
4612 } | 4612 } |
4613 | 4613 |
4614 stream->recv_window = window; | 4614 stream->recv_window = window; |
4615 | 4615 |
4616 return NGX_AGAIN; | 4616 return NGX_AGAIN; |