<feed xmlns='http://www.w3.org/2005/Atom'>
<title>nginx.git/src/http/v3/ngx_http_v3_request.c, branch release-1.28.2</title>
<subtitle>nginx</subtitle>
<link rel='alternate' type='text/html' href='https://git.sigsegv.uk/nginx.git/'/>
<entry>
<title>HTTP/3: fixed handling of :authority and Host with port.</title>
<updated>2025-12-23T18:40:33+00:00</updated>
<author>
<name>Roman Arutyunyan</name>
<email>arut@nginx.com</email>
</author>
<published>2025-06-26T16:19:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.sigsegv.uk/nginx.git/commit/?id=bbf65b6e87dfc7f3a42651a55406e214a783808c'/>
<id>bbf65b6e87dfc7f3a42651a55406e214a783808c</id>
<content type='text'>
RFC 9114, Section 4.3.1. specifies a restriction for :authority and Host
coexistence in an HTTP/3 request:

: If both fields are present, they MUST contain the same value.

Previously, this restriction was correctly enforced only for portless
values.  When Host contained a port, the request failed as if :authority
and Host were different, regardless of :authority presence.

This happens because the value of r-&gt;headers_in.server used for :authority
has port stripped.  The fix is to use r-&gt;host_start / r-&gt;host_end instead.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
RFC 9114, Section 4.3.1. specifies a restriction for :authority and Host
coexistence in an HTTP/3 request:

: If both fields are present, they MUST contain the same value.

Previously, this restriction was correctly enforced only for portless
values.  When Host contained a port, the request failed as if :authority
and Host were different, regardless of :authority presence.

This happens because the value of r-&gt;headers_in.server used for :authority
has port stripped.  The fix is to use r-&gt;host_start / r-&gt;host_end instead.
</pre>
</div>
</content>
</entry>
<entry>
<title>HTTP/3: decoder stream pre-creation.</title>
<updated>2024-05-28T13:18:28+00:00</updated>
<author>
<name>Roman Arutyunyan</name>
<email>arut@nginx.com</email>
</author>
<published>2024-05-28T13:18:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.sigsegv.uk/nginx.git/commit/?id=0fd59c8b565c4577f7c25b9e6450bd311d18f5e2'/>
<id>0fd59c8b565c4577f7c25b9e6450bd311d18f5e2</id>
<content type='text'>
Previously a decoder stream was created on demand for sending Section
Acknowledgement, Stream Cancellation and Insert Count Increment.  If conditions
for sending any of these instructions never happen, a decoder stream is not
created at all.  These conditions include client not using the dynamic table and
no streams abandoned by server (RFC 9204, Section 2.2.2.2).  However RFC 9204,
Section 4.2 defines only one condition for not creating a decoder stream:

   An endpoint MAY avoid creating a decoder stream if its decoder sets
   the maximum capacity of the dynamic table to zero.

The change enables pre-creation of the decoder stream at HTTP/3 session
initialization if maximum dynamic table capacity is not zero.  Note that this
value is currently hardcoded to 4096 bytes and is not configurable, so the
stream is now always created.

Also, the change fixes a potential stack overflow when creating a decoder
stream in ngx_http_v3_send_cancel_stream() while draining a request stream by
ngx_drain_connections().  Creating a decoder stream involves calling
ngx_get_connection(), which calls ngx_drain_connections(), which will drain the
same request stream again.  If client's MAX_STREAMS for uni stream is high
enough, these recursive calls will continue until we run out of stack.
Otherwise, decoder stream creation will fail at some point and the request
stream connection will be drained.  This may result in use-after-free, since
this connection could still be referenced up the stack.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously a decoder stream was created on demand for sending Section
Acknowledgement, Stream Cancellation and Insert Count Increment.  If conditions
for sending any of these instructions never happen, a decoder stream is not
created at all.  These conditions include client not using the dynamic table and
no streams abandoned by server (RFC 9204, Section 2.2.2.2).  However RFC 9204,
Section 4.2 defines only one condition for not creating a decoder stream:

   An endpoint MAY avoid creating a decoder stream if its decoder sets
   the maximum capacity of the dynamic table to zero.

The change enables pre-creation of the decoder stream at HTTP/3 session
initialization if maximum dynamic table capacity is not zero.  Note that this
value is currently hardcoded to 4096 bytes and is not configurable, so the
stream is now always created.

Also, the change fixes a potential stack overflow when creating a decoder
stream in ngx_http_v3_send_cancel_stream() while draining a request stream by
ngx_drain_connections().  Creating a decoder stream involves calling
ngx_get_connection(), which calls ngx_drain_connections(), which will drain the
same request stream again.  If client's MAX_STREAMS for uni stream is high
enough, these recursive calls will continue until we run out of stack.
Otherwise, decoder stream creation will fail at some point and the request
stream connection will be drained.  This may result in use-after-free, since
this connection could still be referenced up the stack.
</pre>
</div>
</content>
</entry>
<entry>
<title>HTTP/3: fixed handling of malformed request body length.</title>
<updated>2024-05-03T16:28:32+00:00</updated>
<author>
<name>Sergey Kandaurov</name>
<email>pluknet@nginx.com</email>
</author>
<published>2024-05-03T16:28:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.sigsegv.uk/nginx.git/commit/?id=a7e3cd52e0a03286267177aa9b88d64232fbaeaf'/>
<id>a7e3cd52e0a03286267177aa9b88d64232fbaeaf</id>
<content type='text'>
Previously, a request body larger than declared in Content-Length resulted in
a 413 status code, because Content-Length was mistakenly used as the maximum
allowed request body, similar to client_max_body_size.  Following the HTTP/3
specification, such requests are now rejected with the 400 error as malformed.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously, a request body larger than declared in Content-Length resulted in
a 413 status code, because Content-Length was mistakenly used as the maximum
allowed request body, similar to client_max_body_size.  Following the HTTP/3
specification, such requests are now rejected with the 400 error as malformed.
</pre>
</div>
</content>
</entry>
<entry>
<title>HTTP/3: postponed session creation to init() callback.</title>
<updated>2023-09-14T10:13:43+00:00</updated>
<author>
<name>Roman Arutyunyan</name>
<email>arut@nginx.com</email>
</author>
<published>2023-09-14T10:13:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.sigsegv.uk/nginx.git/commit/?id=26e606a6bcdfa4001bfb6bd24612e8aafa6513b2'/>
<id>26e606a6bcdfa4001bfb6bd24612e8aafa6513b2</id>
<content type='text'>
Now the session object is assigned to c-&gt;data while ngx_http_connection_t
object is referenced by its http_connection field, similar to
ngx_http_v2_connection_t and ngx_http_request_t.

The change allows to eliminate v3_session field from ngx_http_connection_t.
The field was under NGX_HTTP_V3 macro, which was a source of binary
compatibility problems when nginx/module is build with/without HTTP/3 support.

Postponing is essential since c-&gt;data should retain the reference to
ngx_http_connection_t object throughout QUIC handshake, because SSL callbacks
ngx_http_ssl_servername() and ngx_http_ssl_alpn_select() rely on this.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Now the session object is assigned to c-&gt;data while ngx_http_connection_t
object is referenced by its http_connection field, similar to
ngx_http_v2_connection_t and ngx_http_request_t.

The change allows to eliminate v3_session field from ngx_http_connection_t.
The field was under NGX_HTTP_V3 macro, which was a source of binary
compatibility problems when nginx/module is build with/without HTTP/3 support.

Postponing is essential since c-&gt;data should retain the reference to
ngx_http_connection_t object throughout QUIC handshake, because SSL callbacks
ngx_http_ssl_servername() and ngx_http_ssl_alpn_select() rely on this.
</pre>
</div>
</content>
</entry>
<entry>
<title>HTTP/3: moved variable initialization.</title>
<updated>2023-09-13T13:57:13+00:00</updated>
<author>
<name>Roman Arutyunyan</name>
<email>arut@nginx.com</email>
</author>
<published>2023-09-13T13:57:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.sigsegv.uk/nginx.git/commit/?id=ec37134416d4fd98d8cb8f02776a711c50398684'/>
<id>ec37134416d4fd98d8cb8f02776a711c50398684</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>QUIC: "handshake_timeout" configuration parameter.</title>
<updated>2023-09-13T13:59:37+00:00</updated>
<author>
<name>Roman Arutyunyan</name>
<email>arut@nginx.com</email>
</author>
<published>2023-09-13T13:59:37+00:00</published>
<link rel='alternate' type='text/html' href='https://git.sigsegv.uk/nginx.git/commit/?id=33dca887925d9cec7153252dcd5380c394090936'/>
<id>33dca887925d9cec7153252dcd5380c394090936</id>
<content type='text'>
Previously QUIC did not have such parameter and handshake duration was
controlled by HTTP/3.  However that required creating and storing HTTP/3
session on first client datagram.  Apparently there's no convenient way to
store the session object until QUIC handshake is complete.  In the followup
patches session creation will be postponed to init() callback.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously QUIC did not have such parameter and handshake duration was
controlled by HTTP/3.  However that required creating and storing HTTP/3
session on first client datagram.  Apparently there's no convenient way to
store the session object until QUIC handshake is complete.  In the followup
patches session creation will be postponed to init() callback.
</pre>
</div>
</content>
</entry>
<entry>
<title>HTTP/3: removed "http3" parameter of "listen" directive.</title>
<updated>2023-05-11T09:22:10+00:00</updated>
<author>
<name>Roman Arutyunyan</name>
<email>arut@nginx.com</email>
</author>
<published>2023-05-11T09:22:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.sigsegv.uk/nginx.git/commit/?id=2ce3eeeeb76318e414b62d399da70872d2de23d8'/>
<id>2ce3eeeeb76318e414b62d399da70872d2de23d8</id>
<content type='text'>
The parameter has been deprecated since c851a2ed5ce8.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The parameter has been deprecated since c851a2ed5ce8.
</pre>
</div>
</content>
</entry>
<entry>
<title>HTTP/3: "quic" parameter of "listen" directive.</title>
<updated>2023-02-27T10:00:56+00:00</updated>
<author>
<name>Roman Arutyunyan</name>
<email>arut@nginx.com</email>
</author>
<published>2023-02-27T10:00:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.sigsegv.uk/nginx.git/commit/?id=815ef96124176baef4e940c4beaec158305b368a'/>
<id>815ef96124176baef4e940c4beaec158305b368a</id>
<content type='text'>
Now "listen" directve has a new "quic" parameter which enables QUIC protocol
for the address.  Further, to enable HTTP/3, a new directive "http3" is
introduced.  The hq-interop protocol is enabled by "http3_hq" as before.
Now application protocol is chosen by ALPN.

Previously used "http3" parameter of "listen" is deprecated.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Now "listen" directve has a new "quic" parameter which enables QUIC protocol
for the address.  Further, to enable HTTP/3, a new directive "http3" is
introduced.  The hq-interop protocol is enabled by "http3_hq" as before.
Now application protocol is chosen by ALPN.

Previously used "http3" parameter of "listen" is deprecated.
</pre>
</div>
</content>
</entry>
<entry>
<title>HTTP/3: insert count block timeout.</title>
<updated>2023-01-05T15:03:22+00:00</updated>
<author>
<name>Roman Arutyunyan</name>
<email>arut@nginx.com</email>
</author>
<published>2023-01-05T15:03:22+00:00</published>
<link rel='alternate' type='text/html' href='https://git.sigsegv.uk/nginx.git/commit/?id=0065ba68b08b8cf4eaf3c18266d1a93182f196ed'/>
<id>0065ba68b08b8cf4eaf3c18266d1a93182f196ed</id>
<content type='text'>
Previously, there was no timeout for a request stream blocked on insert count,
which could result in infinite wait.  Now client_header_timeout is set when
stream is first blocked.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously, there was no timeout for a request stream blocked on insert count,
which could result in infinite wait.  Now client_header_timeout is set when
stream is first blocked.
</pre>
</div>
</content>
</entry>
<entry>
<title>HTTP/3: trigger 400 (Bad Request) on stream error while blocked.</title>
<updated>2023-01-05T14:15:46+00:00</updated>
<author>
<name>Roman Arutyunyan</name>
<email>arut@nginx.com</email>
</author>
<published>2023-01-05T14:15:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.sigsegv.uk/nginx.git/commit/?id=faa655f211612fcdac938d58095a4ab7f03969a9'/>
<id>faa655f211612fcdac938d58095a4ab7f03969a9</id>
<content type='text'>
Previously, stream was closed with NGX_HTTP_CLOSE.  However, in a similar case
when recv() returns eof or error, status 400 is triggered.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously, stream was closed with NGX_HTTP_CLOSE.  However, in a similar case
when recv() returns eof or error, status 400 is triggered.
</pre>
</div>
</content>
</entry>
</feed>
