[PATCH] HTTP/2: made it possible to flush response headers (ticket #1743)
Sergey Kandaurov
pluknet at nginx.com
Tue Feb 1 15:24:47 UTC 2022
> On 27 Jan 2022, at 04:24, Maxim Dounin <mdounin at mdounin.ru> wrote:
>
> # HG changeset patch
> # User Maxim Dounin <mdounin at mdounin.ru>
> # Date 1643225036 -10800
> # Wed Jan 26 22:23:56 2022 +0300
> # Node ID f76e0cf8e525996563e5f0092fa48a4fee873e93
> # Parent 56ead48cfe885e8b89b30017459bf621b21d95f5
> HTTP/2: made it possible to flush response headers (ticket #1743).
>
> Response headers can be buffered in the SSL buffer. But stream's fake
> connection buffered flag did not reflect this, so any attempts to flush
> the buffer without sending additional data were stopped by the write filter.
>
> It does not seem to be possible to reflect this in fc->buffered though, as
> we never known if main connection's c->buffered corresponds to the particular
> stream or not. As such, fc->buffered might prevent request finalization
> due to sending data on some other stream.
>
> Fix is to implement handling of flush buffers when c->need_last_buf is set,
> similarly to the existing last buffer handling.
>
> diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c
> --- a/src/http/ngx_http_write_filter_module.c
> +++ b/src/http/ngx_http_write_filter_module.c
> @@ -227,7 +227,7 @@ ngx_http_write_filter(ngx_http_request_t
>
> if (size == 0
> && !(c->buffered & NGX_LOWLEVEL_BUFFERED)
> - && !(last && c->need_last_buf))
> + && !((last || flush) && c->need_last_buf))
> {
> if (last || flush || sync) {
> for (cl = r->out; cl; /* void */) {
> diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c
> --- a/src/http/v2/ngx_http_v2_filter_module.c
> +++ b/src/http/v2/ngx_http_v2_filter_module.c
> @@ -1815,7 +1815,11 @@ ngx_http_v2_waiting_queue(ngx_http_v2_co
> static ngx_inline ngx_int_t
> ngx_http_v2_filter_send(ngx_connection_t *fc, ngx_http_v2_stream_t *stream)
> {
> - if (stream->queued == 0) {
> + ngx_connection_t *c;
> +
> + c = stream->connection->connection;
> +
> + if (stream->queued == 0 && !c->buffered) {
> fc->buffered &= ~NGX_HTTP_V2_BUFFERED;
> return NGX_OK;
> }
>
Nitpicking:
Shouldn't NGX_HTTP_V2_BUFFERED still be cleared regardless?
if (stream->queued == 0) {
fc->buffered &= ~NGX_HTTP_V2_BUFFERED;
if (!c->buffered) {
return NGX_OK;
}
}
It doesn't seem to change anything, at a glance.
However, this would save a contract that
(fc->buffered & NGX_HTTP_V2_BUFFERED) is influenced by stream->queued.
Otherwise, looks good.
--
Sergey Kandaurov
More information about the nginx-devel
mailing list