Skip to content

Commit 360322d

Browse files
committed
reject request without the Host header
1 parent a618a87 commit 360322d

3 files changed

Lines changed: 15 additions & 3 deletions

File tree

aiohttp/_http_parser.pyx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ cdef class HttpParser:
437437
cdef _on_headers_complete(self):
438438
self._process_header()
439439

440+
http_version = self.http_version()
440441
should_close = not cparser.llhttp_should_keep_alive(self._cparser)
441442
upgrade = self._cparser.upgrade
442443
chunked = self._cparser.flags & cparser.F_CHUNKED
@@ -453,6 +454,8 @@ cdef class HttpParser:
453454
raise BadHttpMessage(f"Duplicate '{bad_hdr}' header found.")
454455

455456
if self._cparser.type == cparser.HTTP_REQUEST:
457+
if http_version == HttpVersion11 and hdrs.HOST not in headers:
458+
raise BadHttpMessage("Missing 'Host' header in request.")
456459
h_upg = headers.get("upgrade", "")
457460
allowed = upgrade and h_upg.isascii() and h_upg.lower() in ALLOWED_UPGRADES
458461
if allowed or self._cparser.method == cparser.HTTP_CONNECT:
@@ -476,11 +479,11 @@ cdef class HttpParser:
476479
method = http_method_str(self._cparser.method)
477480
msg = _new_request_message(
478481
method, self._path,
479-
self.http_version(), headers, raw_headers,
482+
http_version, headers, raw_headers,
480483
should_close, encoding, upgrade, chunked, self._url)
481484
else:
482485
msg = _new_response_message(
483-
self.http_version(), self._cparser.status_code, self._reason,
486+
http_version, self._cparser.status_code, self._reason,
484487
headers, raw_headers, should_close, encoding,
485488
upgrade, chunked)
486489

aiohttp/http_parser.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
LineTooLong,
4242
TransferEncodingError,
4343
)
44-
from .http_writer import HttpVersion, HttpVersion10
44+
from .http_writer import HttpVersion, HttpVersion10, HttpVersion11
4545
from .streams import EMPTY_PAYLOAD, StreamReader
4646
from .typedefs import RawHeaders
4747

@@ -627,6 +627,9 @@ def parse_message(self, lines: list[bytes]) -> RawRequestMessage:
627627
chunked,
628628
) = self.parse_headers(lines[1:])
629629

630+
if version_o == HttpVersion11 and hdrs.HOST not in headers:
631+
raise BadHttpMessage("Missing 'Host' header in request.")
632+
630633
if close is None: # then the headers weren't set in the request
631634
if version_o <= HttpVersion10: # HTTP 1.0 must asks to not close
632635
close = True

tests/test_http_parser.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,12 @@ def test_duplicate_host_header_rejected(parser: HttpRequestParser) -> None:
318318
parser.feed_data(text)
319319

320320

321+
def test_missing_host_header_rejected(parser: HttpRequestParser) -> None:
322+
text = b"GET /admin HTTP/1.1\r\n\r\n"
323+
with pytest.raises(http_exceptions.BadHttpMessage, match="Missing 'Host' header"):
324+
parser.feed_data(text)
325+
326+
321327
def test_bad_chunked(parser: HttpRequestParser) -> None:
322328
"""Test that invalid chunked encoding doesn't allow content-length to be used."""
323329
text = (

0 commit comments

Comments
 (0)