Address PR #3468 review feedback

- Guard early_hints callback against calls after response started
- Fix :authority precedence over Host header per RFC 9113 section 8.3.1
- Add nginx early_hints documentation link
- Use standard port 443 in curl examples
This commit is contained in:
Benoit Chesneau 2026-01-26 11:10:01 +01:00
parent ed94da449c
commit 66d0880c74
3 changed files with 15 additions and 7 deletions

View File

@ -225,7 +225,7 @@ server {
!!! note
For nginx to forward 103 Early Hints from upstream, you need nginx 1.29+
and the `early_hints` directive.
and the [`early_hints`](https://nginx.org/en/docs/http/ngx_http_core_module.html#early_hints) directive.
### Direct TLS Termination
@ -312,10 +312,10 @@ http2_max_concurrent_streams = 200 # Increase from default 100
```bash
# Check HTTP/2 support
curl -v --http2 https://localhost:8443/
curl -v --http2 https://localhost:443/
# Force HTTP/2
curl --http2-prior-knowledge https://localhost:8443/
curl --http2-prior-knowledge https://localhost:443/
```
### Using Python

View File

@ -107,7 +107,7 @@ def proxy_environ(req):
}
def _make_early_hints_callback(req, sock):
def _make_early_hints_callback(req, sock, resp):
"""Create a wsgi.early_hints callback for sending 103 Early Hints.
This allows WSGI applications to send 103 Early Hints responses
@ -116,6 +116,7 @@ def _make_early_hints_callback(req, sock):
Args:
req: The request object
sock: The socket to write to
resp: The Response object to check if headers have been sent
Returns:
A callback function that accepts a list of (name, value) header tuples
@ -125,6 +126,7 @@ def _make_early_hints_callback(req, sock):
- Early hints are only sent for HTTP/1.1 or later clients
- HTTP/1.0 clients will silently ignore the callback
- Multiple calls are allowed (sending multiple 103 responses)
- Calls after response has started are silently ignored
"""
def send_early_hints(headers):
"""Send 103 Early Hints response.
@ -133,6 +135,10 @@ def _make_early_hints_callback(req, sock):
headers: List of (name, value) header tuples, typically Link headers
Example: [('Link', '</style.css>; rel=preload; as=style')]
"""
# Don't send after response has started - would break framing
if resp.headers_sent:
return
# Don't send to HTTP/1.0 clients - they don't support 1xx responses
if req.version < (1, 1):
return
@ -242,7 +248,7 @@ def create(req, sock, client, server, cfg):
environ.update(proxy_environ(req))
# Add wsgi.early_hints callback for sending 103 Early Hints
environ['wsgi.early_hints'] = _make_early_hints_callback(req, sock)
environ['wsgi.early_hints'] = _make_early_hints_callback(req, sock, resp)
return resp, environ

View File

@ -133,8 +133,10 @@ class HTTP2Request:
# Convert to uppercase for WSGI compatibility
self.headers.append((name.upper(), value))
# Add Host header if not present (from :authority)
if authority and not any(h[0] == 'HOST' for h in self.headers):
# Set Host header from :authority (RFC 9113 section 8.3.1)
# :authority MUST take precedence over Host header
if authority:
self.headers = [(n, v) for n, v in self.headers if n != 'HOST']
self.headers.append(('HOST', authority))
# Trailers (if any)