{"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":"http","errorClass":"BadHttpMethod","httpStatus":400,"severity":"error","filePath":"aiohttp/http_parser.py","lineNumber":659,"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":641,"sourceCodeEnd":677,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/http_parser.py#L641-L677","documentation":"Raised by HttpRequestParser.parse_message (aiohttp/http_parser.py:659) when the request line cannot be split into three tokens (method, request-target, version) via str.split(' ', maxsplit=2). A ValueError (too few parts) is caught and re-raised as BadHttpMethod(line). Special case: if the line starts with '\\x16\\x03' (a TLS record header), BadHttpMethod sets the message to 'Received HTTPS traffic on an HTTP port'.","triggerScenarios":"A request line with fewer than two spaces, e.g. 'GET\\r\\n' (method only), 'GET /index\\r\\n' (no version), an empty line, or pure garbage. The single most common real-world trigger is an HTTPS ClientHello ('\\x16\\x03...') arriving on a plaintext HTTP port.","commonSituations":"HTTPS client pointed at an HTTP port (or vice versa), port scanners, raw socket/telnet tests, or a client that forgot the HTTP version token when hand-building the request line.","solutions":["Point HTTPS clients at the HTTPS port and HTTP clients at the HTTP port.","Ensure the request line has the form 'METHOD SP REQUEST-TARGET SP HTTP-VERSION' (three tokens).","If building raw requests, include all three tokens separated by single spaces.","Use a real HTTP library that formats the request line correctly."],"exampleFix":"# before - TLS traffic to the plaintext port\nclient = ssl.wrap_socket(sock)   # then connect to host:80\n# after - match scheme to port\n# http://host:80/  OR  https://host:443/\n# raw-client fix:\nsock.send(b'GET / HTTP/1.1\\r\\nHost: example.com\\r\\n\\r\\n')","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from aiohttp import http_exceptions\ntry:\n    await request.read()\nexcept http_exceptions.BadStatusLine as e:\n    line = getattr(e, 'line', '')\n    if line.startswith('\\x16\\x03'):\n        log.warning('HTTPS traffic on HTTP port from %s', request.remote)\n    return web.Response(status=400)","preventionTips":["Match the client scheme (http/https) to the server port","Always send a complete three-token request line","Use an HTTP library rather than raw sockets"],"tags":["http","protocol","parser","tls","request-line"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}