Skip to content

Commit 74a818a

Browse files
committed
fix default handling of HTTP/0.9 requests
1 parent 46a1f0a commit 74a818a

File tree

3 files changed

+47
-16
lines changed

3 files changed

+47
-16
lines changed

Lib/http/server.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ def parse_request(self):
302302
error response has already been sent back.
303303
304304
"""
305+
is_http_0_9 = False
305306
self.command = None # set in case of error on the first line
306307
self.request_version = version = self.default_request_version
307308
self.close_connection = True
@@ -359,6 +360,7 @@ def parse_request(self):
359360
HTTPStatus.BAD_REQUEST,
360361
"Bad HTTP/0.9 request type (%r)" % command)
361362
return False
363+
is_http_0_9 = True
362364
self.command, self.path = command, path
363365

364366
# gh-87389: The purpose of replacing '//' with '/' is to protect
@@ -369,22 +371,26 @@ def parse_request(self):
369371
self.path = '/' + self.path.lstrip('/') # Reduce to a single /
370372

371373
# Examine the headers and look for a Connection directive.
372-
try:
373-
self.headers = http.client.parse_headers(self.rfile,
374-
_class=self.MessageClass)
375-
except http.client.LineTooLong as err:
376-
self.send_error(
377-
HTTPStatus.REQUEST_HEADER_FIELDS_TOO_LARGE,
378-
"Line too long",
379-
str(err))
380-
return False
381-
except http.client.HTTPException as err:
382-
self.send_error(
383-
HTTPStatus.REQUEST_HEADER_FIELDS_TOO_LARGE,
384-
"Too many headers",
385-
str(err)
386-
)
387-
return False
374+
# For HTTP/0.9, headers are not expected at all.
375+
if is_http_0_9:
376+
self.headers = {}
377+
else:
378+
try:
379+
self.headers = http.client.parse_headers(self.rfile,
380+
_class=self.MessageClass)
381+
except http.client.LineTooLong as err:
382+
self.send_error(
383+
HTTPStatus.REQUEST_HEADER_FIELDS_TOO_LARGE,
384+
"Line too long",
385+
str(err))
386+
return False
387+
except http.client.HTTPException as err:
388+
self.send_error(
389+
HTTPStatus.REQUEST_HEADER_FIELDS_TOO_LARGE,
390+
"Too many headers",
391+
str(err)
392+
)
393+
return False
388394

389395
conntype = self.headers.get('Connection', "")
390396
if conntype.lower() == 'close':

Lib/test/test_httpservers.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,26 @@ def test_head_via_send_error(self):
362362
self.assertEqual(b'', data)
363363

364364

365+
class HTTP09ServerTestCase(BaseTestCase):
366+
367+
class request_handler(NoLogRequestHandler, BaseHTTPRequestHandler):
368+
"""Request handler for HTTP/0.9 server."""
369+
370+
def do_GET(self):
371+
self.wfile.write(f'OK: here is {self.path}\r\n'.encode())
372+
373+
def setUp(self):
374+
super().setUp()
375+
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
376+
self.sock = self.enterContext(self.sock)
377+
self.sock.connect((self.HOST, self.PORT))
378+
379+
def test_http_0_9_server(self):
380+
self.sock.send(b'GET /index.html\r\n')
381+
res = self.sock.recv(1024)
382+
self.assertEqual(res, b"OK: here is /index.html\r\n")
383+
384+
365385
def certdata_file(*path):
366386
return os.path.join(os.path.dirname(__file__), "certdata", *path)
367387

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
:mod:`http.server`: fix default handling of HTTP/0.9 requests in
2+
:class:`~http.server.BaseHTTPRequestHandler`. Previously,
3+
:meth:`!BaseHTTPRequestHandler.parse_request`` incorrectly
4+
waited for headers in the request although those are not
5+
supported in HTTP/0.9. Patch by Bénédikt Tran.

0 commit comments

Comments
 (0)