Skip to content

Commit 38b728b

Browse files
committed
UNFINISHED: refuse conflicting host names
demand case-insensitive match of duplicate headers, or host header sent in url with absolute-form target UNFINISHED: This patch is not compliant with https://datatracker.ietf.org/doc/html/rfc9112#section-3.2.2-6 "When a proxy receives a request with an absolute-form of request-target, the proxy MUST ignore the received Host header field (if any) and instead replace it with the host information of the request-target."
1 parent 6236c2f commit 38b728b

File tree

1 file changed

+14
-0
lines changed

1 file changed

+14
-0
lines changed

gunicorn/http/message.py

+14
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def __init__(self, cfg, unreader, peer_addr):
4646
self.scheme = "https" if cfg.is_ssl else "http"
4747
self.must_close = False
4848
self._expected_100_continue = False
49+
self._seen_netloc = None
4950

5051
# set headers limits
5152
self.limit_request_fields = cfg.limit_request_fields
@@ -136,6 +137,17 @@ def parse_headers(self, data, from_trailer=False):
136137
if header_length > self.limit_request_field_size > 0:
137138
raise LimitRequestHeaders("limit request headers fields size")
138139

140+
if not from_trailer and name == "HOST":
141+
# if we parse the URL and split it for the app
142+
# the app can hold us accountable to get this right
143+
# we cannot get it right when we see conflicting values
144+
if self._seen_netloc is None:
145+
self._seen_netloc = value
146+
else:
147+
# e.g. "HOST.com:443" != "host"
148+
if self._seen_netloc.lower().split(":",1)[0] != value.lower().split(":",1)[0]:
149+
raise InvalidHeader(name)
150+
139151
if not from_trailer and name == "EXPECT":
140152
# unquoted expectations are case-insensitive
141153
if value.lower() == "100-continue":
@@ -465,6 +477,8 @@ def parse_request_line(self, line_bytes):
465477
self.path = parts.path or ""
466478
self.query = parts.query or ""
467479
self.fragment = parts.fragment or ""
480+
if parts.netloc:
481+
self._seen_netloc = parts.netloc
468482

469483
# Version
470484
match = VERSION_RE.fullmatch(bits[2])

0 commit comments

Comments
 (0)