Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PR #7651/45f98b7d backport][3.8] Fix BadStatusLine message #7666

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/7651.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed display of ``BadStatusLine`` messages from ``llhttp`` -- by :user:`Dreamsorcerer`
30 changes: 11 additions & 19 deletions aiohttp/_http_parser.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#
# Based on https://github.com/MagicStack/httptools
#
from __future__ import absolute_import, print_function

from cpython cimport (
Py_buffer,
Expand Down Expand Up @@ -813,7 +812,9 @@ cdef parser_error_from_errno(cparser.llhttp_t* parser, data, pointer):
cdef cparser.llhttp_errno_t errno = cparser.llhttp_get_errno(parser)
cdef bytes desc = cparser.llhttp_get_error_reason(parser)

if errno in (cparser.HPE_CB_MESSAGE_BEGIN,
err_msg = "{}:\n\n {!r}\n {}".format(desc.decode("latin-1"), data, pointer)

if errno in {cparser.HPE_CB_MESSAGE_BEGIN,
cparser.HPE_CB_HEADERS_COMPLETE,
cparser.HPE_CB_MESSAGE_COMPLETE,
cparser.HPE_CB_CHUNK_HEADER,
Expand All @@ -823,22 +824,13 @@ cdef parser_error_from_errno(cparser.llhttp_t* parser, data, pointer):
cparser.HPE_INVALID_CONTENT_LENGTH,
cparser.HPE_INVALID_CHUNK_SIZE,
cparser.HPE_INVALID_EOF_STATE,
cparser.HPE_INVALID_TRANSFER_ENCODING):
cls = BadHttpMessage

elif errno == cparser.HPE_INVALID_STATUS:
cls = BadStatusLine

elif errno == cparser.HPE_INVALID_METHOD:
cls = BadStatusLine

elif errno == cparser.HPE_INVALID_VERSION:
cls = BadStatusLine

cparser.HPE_INVALID_TRANSFER_ENCODING}:
return BadHttpMessage(err_msg)
elif errno in {cparser.HPE_INVALID_STATUS,
cparser.HPE_INVALID_METHOD,
cparser.HPE_INVALID_VERSION}:
return BadStatusLine(error=err_msg)
elif errno == cparser.HPE_INVALID_URL:
cls = InvalidURLError

else:
cls = BadHttpMessage
return InvalidURLError(err_msg)

return cls("{}:\n\n {!r}\n {}".format(desc.decode("latin-1"), data, pointer))
return BadHttpMessage(err_msg)
4 changes: 2 additions & 2 deletions aiohttp/http_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,10 @@ def __init__(self, hdr: Union[bytes, str]) -> None:


class BadStatusLine(BadHttpMessage):
def __init__(self, line: str = "") -> None:
def __init__(self, line: str = "", error: Optional[str] = None) -> None:
if not isinstance(line, str):
line = repr(line)
super().__init__(f"Bad status line {line!r}")
super().__init__(error or f"Bad status line {line!r}")
self.args = (line,)
self.line = line

Expand Down
4 changes: 3 additions & 1 deletion tests/test_http_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -649,8 +649,10 @@ def test_http_request_parser(parser) -> None:

def test_http_request_bad_status_line(parser) -> None:
text = b"getpath \r\n\r\n"
with pytest.raises(http_exceptions.BadStatusLine):
with pytest.raises(http_exceptions.BadStatusLine) as exc_info:
parser.feed_data(text)
# Check for accidentally escaped message.
assert r"\n" not in exc_info.value.message


def test_http_request_upgrade(parser) -> None:
Expand Down