[Python-checkins] cpython: Issue #28548: Parse HTTP request version even if too many words received

martin.panter python-checkins at python.org
Fri Nov 18 20:19:26 EST 2016


https://hg.python.org/cpython/rev/7c98768368cb
changeset:   105185:7c98768368cb
user:        Martin Panter <vadmium+py at gmail.com>
date:        Sat Nov 19 01:06:37 2016 +0000
summary:
  Issue #28548: Parse HTTP request version even if too many words received

files:
  Lib/http/server.py           |  33 +++++++++++++----------
  Lib/test/test_httpservers.py |  10 +++++++
  Misc/NEWS                    |   3 ++
  3 files changed, 31 insertions(+), 15 deletions(-)


diff --git a/Lib/http/server.py b/Lib/http/server.py
--- a/Lib/http/server.py
+++ b/Lib/http/server.py
@@ -267,8 +267,8 @@
         are in self.command, self.path, self.request_version and
         self.headers.
 
-        Return True for success, False for failure; on failure, an
-        error is sent back.
+        Return True for success, False for failure; on failure, any relevant
+        error response has already been sent back.
 
         """
         self.command = None  # set in case of error on the first line
@@ -278,10 +278,13 @@
         requestline = requestline.rstrip('\r\n')
         self.requestline = requestline
         words = requestline.split()
-        if len(words) == 3:
-            command, path, version = words
+        if len(words) == 0:
+            return False
+
+        if len(words) >= 3:  # Enough to determine protocol version
+            version = words[-1]
             try:
-                if version[:5] != 'HTTP/':
+                if not version.startswith('HTTP/'):
                     raise ValueError
                 base_version_number = version.split('/', 1)[1]
                 version_number = base_version_number.split(".")
@@ -306,22 +309,22 @@
                     HTTPStatus.HTTP_VERSION_NOT_SUPPORTED,
                     "Invalid HTTP version (%s)" % base_version_number)
                 return False
-        elif len(words) == 2:
-            command, path = words
+            self.request_version = version
+
+        if not 2 <= len(words) <= 3:
+            self.send_error(
+                HTTPStatus.BAD_REQUEST,
+                "Bad request syntax (%r)" % requestline)
+            return False
+        command, path = words[:2]
+        if len(words) == 2:
             self.close_connection = True
             if command != 'GET':
                 self.send_error(
                     HTTPStatus.BAD_REQUEST,
                     "Bad HTTP/0.9 request type (%r)" % command)
                 return False
-        elif not words:
-            return False
-        else:
-            self.send_error(
-                HTTPStatus.BAD_REQUEST,
-                "Bad request syntax (%r)" % requestline)
-            return False
-        self.command, self.path, self.request_version = command, path, version
+        self.command, self.path = command, path
 
         # Examine the headers and look for a Connection directive.
         try:
diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py
--- a/Lib/test/test_httpservers.py
+++ b/Lib/test/test_httpservers.py
@@ -822,6 +822,16 @@
         self.assertEqual(result[0], b'<html><body>Data</body></html>\r\n')
         self.verify_get_called()
 
+    def test_extra_space(self):
+        result = self.send_typical_request(
+            b'GET /spaced out HTTP/1.1\r\n'
+            b'Host: dummy\r\n'
+            b'\r\n'
+        )
+        self.assertTrue(result[0].startswith(b'HTTP/1.1 400 '))
+        self.verify_expected_headers(result[1:result.index(b'\r\n')])
+        self.assertFalse(self.handler.get_called)
+
     def test_with_continue_1_0(self):
         result = self.send_typical_request(b'GET / HTTP/1.0\r\nExpect: 100-continue\r\n\r\n')
         self.verify_http_server_response(result[0])
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -128,6 +128,9 @@
 Library
 -------
 
+- Issue #28548: In the "http.server" module, parse the protocol version if
+  possible, to avoid using HTTP 0.9 in some error responses.
+
 - Issue #19717: Makes Path.resolve() succeed on paths that do not exist.
   Patch by Vajrasky Kok
 

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list