]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-70765: avoid waiting for HTTP headers when parsing HTTP/0.9 requests (GH...
authorBénédikt Tran <10796600+picnixz@users.noreply.github.com>
Wed, 8 Oct 2025 10:32:45 +0000 (12:32 +0200)
committerGitHub <noreply@github.com>
Wed, 8 Oct 2025 10:32:45 +0000 (10:32 +0000)
(cherry picked from commit 13dc2fde8cec1e8aad04c7635b3da4ff3e3dcb00)
(cherry picked from commit 1fe89d324e6b96dc44a7bd593c428a90d1f39d55)

Lib/http/server.py
Lib/test/test_httpservers.py
Misc/NEWS.d/next/Library/2025-10-02-17-40-10.gh-issue-70765.zVlLZn.rst [new file with mode: 0644]

index 2aed5baf1fff67a5fd095b321012ed6c3f7464e6..758a725f1fd540741e9b9c679af196796a48b84b 100644 (file)
@@ -275,6 +275,7 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler):
         error response has already been sent back.
 
         """
+        is_http_0_9 = False
         self.command = None  # set in case of error on the first line
         self.request_version = version = self.default_request_version
         self.close_connection = True
@@ -332,6 +333,7 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler):
                     HTTPStatus.BAD_REQUEST,
                     "Bad HTTP/0.9 request type (%r)" % command)
                 return False
+            is_http_0_9 = True
         self.command, self.path = command, path
 
         # gh-87389: The purpose of replacing '//' with '/' is to protect
@@ -341,6 +343,11 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler):
         if self.path.startswith('//'):
             self.path = '/' + self.path.lstrip('/')  # Reduce to a single /
 
+        # For HTTP/0.9, headers are not expected at all.
+        if is_http_0_9:
+            self.headers = {}
+            return True
+
         # Examine the headers and look for a Connection directive.
         try:
             self.headers = http.client.parse_headers(self.rfile,
index 140798a927a041380be5022b412adb84fb9591fc..c369baf28fe823153cb67c7f9e15896813dceac2 100644 (file)
@@ -8,6 +8,7 @@ from http.server import BaseHTTPRequestHandler, HTTPServer, \
      SimpleHTTPRequestHandler, CGIHTTPRequestHandler
 from http import server, HTTPStatus
 
+import contextlib
 import os
 import socket
 import sys
@@ -316,6 +317,44 @@ class BaseHTTPServerTestCase(BaseTestCase):
             self.assertEqual(b'', data)
 
 
+class HTTP09ServerTestCase(BaseTestCase):
+
+    class request_handler(NoLogRequestHandler, BaseHTTPRequestHandler):
+        """Request handler for HTTP/0.9 server."""
+
+        def do_GET(self):
+            self.wfile.write(f'OK: here is {self.path}\r\n'.encode())
+
+    def setUp(self):
+        super().setUp()
+        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        self.sock = self.enterContext(self.sock)
+        self.sock.connect((self.HOST, self.PORT))
+
+    def test_simple_get(self):
+        self.sock.send(b'GET /index.html\r\n')
+        res = self.sock.recv(1024)
+        self.assertEqual(res, b"OK: here is /index.html\r\n")
+
+    def test_invalid_request(self):
+        self.sock.send(b'POST /index.html\r\n')
+        res = self.sock.recv(1024)
+        self.assertIn(b"Bad HTTP/0.9 request type ('POST')", res)
+
+    def test_single_request(self):
+        self.sock.send(b'GET /foo.html\r\n')
+        res = self.sock.recv(1024)
+        self.assertEqual(res, b"OK: here is /foo.html\r\n")
+
+        # Ignore errors if the connection is already closed,
+        # as this is the expected behavior of HTTP/0.9.
+        with contextlib.suppress(OSError):
+            self.sock.send(b'GET /bar.html\r\n')
+            res = self.sock.recv(1024)
+            # The server should not process our request.
+            self.assertEqual(res, b'')
+
+
 class RequestHandlerLoggingTestCase(BaseTestCase):
     class request_handler(BaseHTTPRequestHandler):
         protocol_version = 'HTTP/1.1'
diff --git a/Misc/NEWS.d/next/Library/2025-10-02-17-40-10.gh-issue-70765.zVlLZn.rst b/Misc/NEWS.d/next/Library/2025-10-02-17-40-10.gh-issue-70765.zVlLZn.rst
new file mode 100644 (file)
index 0000000..e1a9bbe
--- /dev/null
@@ -0,0 +1,5 @@
+:mod:`http.server`: fix default handling of HTTP/0.9 requests in
+:class:`~http.server.BaseHTTPRequestHandler`. Previously,
+:meth:`!BaseHTTPRequestHandler.parse_request`` incorrectly
+waited for headers in the request although those are not
+supported in HTTP/0.9. Patch by Bénédikt Tran.