{"record":{"id":"4b66f33e6c445998","repo":"aio-libs/aiohttp","slug":"bad-http-method-in-status-line-line-r","errorCode":null,"errorMessage":"Bad HTTP method in status line {line!r}","messagePattern":"Bad HTTP method in status line (.+?)","errorType":"exception","errorClass":"BadHttpMethod","httpStatus":400,"severity":"error","filePath":"aiohttp/http_parser.py","lineNumber":661,"sourceCode":"        \"\"\"\n        self._upgraded = val\n\n\nclass HttpRequestParser(HttpParser[RawRequestMessage]):\n    \"\"\"Read request status line.\n\n    Exception .http_exceptions.BadStatusLine\n    could be raised in case of any errors in status line.\n    Returns RawRequestMessage.\n    \"\"\"\n\n    def parse_message(self, lines: list[bytes]) -> RawRequestMessage:\n        # request line\n        line = lines[0].decode(\"utf-8\", \"surrogateescape\")\n        try:\n            method, path, version = line.split(\" \", maxsplit=2)\n        except ValueError:\n            raise BadHttpMethod(line) from None\n\n        # method\n        if not TOKENRE.fullmatch(method):\n            raise BadHttpMethod(method)\n        method = method.upper()\n\n        # version\n        match = VERSRE.fullmatch(version)\n        if match is None:\n            raise BadStatusLine(line)\n        version_o = HttpVersion(int(match.group(1)), int(match.group(2)))\n\n        if method == \"CONNECT\":\n            # authority-form,\n            # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.3\n            url = URL.build(authority=path, encoded=True)\n        elif path.startswith(\"/\"):\n            # origin-form,","sourceCodeStart":643,"sourceCodeEnd":679,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/http_parser.py#L643-L679","documentation":"Raised when the request line cannot be split into three whitespace-separated tokens (method, path, version) - line.split(' ', maxsplit=2) raises ValueError. Special case: if the line starts with bytes \\x16\\x03 (a TLS record header), the message becomes 'Received HTTPS traffic on an HTTP port'.","triggerScenarios":"A request line with fewer than two spaces ('GET\\r\\n', 'GARBAGE', an empty line), or a TLS ClientHello (\\x16\\x03...) hitting a plaintext HTTP port.","commonSituations":"HTTPS client connecting to a plaintext HTTP port (the \\x16\\x03 case), corrupted requests, raw non-HTTP TCP traffic hitting the HTTP port, fuzzing.","solutions":["For HTTPS-on-HTTP: enable TLS on the aiohttp server or use the correct port/scheme.","For malformed: inspect the raw bytes the peer sent.","Add a protocol-detecting proxy that routes TLS to the TLS port."],"exampleFix":"# before - client uses https:// against port 80\n# after - enable TLS on the server, or use http:// scheme\nssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)\nssl_ctx.load_cert_chain('cert.pem', 'key.pem')\nawait web.TCPSite(runner, port=443, ssl_context=ssl_ctx).start()","handlingStrategy":"try-catch","validationCode":"# cannot 'validate' remote bytes; detect TLS-on-HTTP at the edge instead\ndef looks_like_tls(first_bytes: bytes) -> bool:\n    return first_bytes[:2] == b'\\x16\\x03'","typeGuard":"def looks_like_tls(first_bytes: bytes) -> bool:\n    return first_bytes[:2] == b'\\x16\\x03'","tryCatchPattern":"from aiohttp.http_exceptions import BadHttpMethod, BadHttpMessage\ntry:\n    ...parse...\nexcept BadHttpMethod as e:\n    if 'HTTPS traffic on an HTTP port' in str(e):\n        # terminate or redirect to the TLS port\n        ...","preventionTips":["Separate TLS and plaintext listeners on different ports.","When using raw sockets, sanity-check the first bytes before assuming HTTP."],"tags":["http","parser","request-line","tls","security"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}