[Python-checkins] cpython (merge 3.4 -> default): merge 3.4 (#23410)

benjamin.peterson python-checkins at python.org
Wed Feb 18 03:13:34 CET 2015


https://hg.python.org/cpython/rev/6e3e252cf047
changeset:   94673:6e3e252cf047
parent:      94671:9a55a2a1dc6f
parent:      94672:f9ff2a5bbbe2
user:        Benjamin Peterson <benjamin at python.org>
date:        Tue Feb 17 21:13:30 2015 -0500
summary:
  merge 3.4 (#23410)

files:
  Doc/library/http.server.rst  |  12 +++++++
  Lib/http/server.py           |  20 ++++++------
  Lib/test/test_httpservers.py |  39 ++++++++++++++++++++++++
  3 files changed, 61 insertions(+), 10 deletions(-)


diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst
--- a/Doc/library/http.server.rst
+++ b/Doc/library/http.server.rst
@@ -64,6 +64,18 @@
 
       Contains the server instance.
 
+   .. attribute:: close_connection
+
+      Boolean that should be set before :meth:`handle_one_request` returns,
+      indicating if another request may be expected, or if the connection should
+      be shut down.
+
+   .. attribute:: requestline
+
+      Contains the string representation of the HTTP request line. The
+      terminating CRLF is stripped. This attribute should be set by
+      :meth:`handle_one_request`. If no valid request line was processed, it
+      should be set to the empty string.
 
    .. attribute:: command
 
diff --git a/Lib/http/server.py b/Lib/http/server.py
--- a/Lib/http/server.py
+++ b/Lib/http/server.py
@@ -275,7 +275,7 @@
         """
         self.command = None  # set in case of error on the first line
         self.request_version = version = self.default_request_version
-        self.close_connection = 1
+        self.close_connection = True
         requestline = str(self.raw_requestline, 'iso-8859-1')
         requestline = requestline.rstrip('\r\n')
         self.requestline = requestline
@@ -305,7 +305,7 @@
                     "Bad request version (%r)" % version)
                 return False
             if version_number >= (1, 1) and self.protocol_version >= "HTTP/1.1":
-                self.close_connection = 0
+                self.close_connection = False
             if version_number >= (2, 0):
                 self.send_error(
                     HTTPStatus.HTTP_VERSION_NOT_SUPPORTED,
@@ -313,7 +313,7 @@
                 return False
         elif len(words) == 2:
             command, path = words
-            self.close_connection = 1
+            self.close_connection = True
             if command != 'GET':
                 self.send_error(
                     HTTPStatus.BAD_REQUEST,
@@ -340,10 +340,10 @@
 
         conntype = self.headers.get('Connection', "")
         if conntype.lower() == 'close':
-            self.close_connection = 1
+            self.close_connection = True
         elif (conntype.lower() == 'keep-alive' and
               self.protocol_version >= "HTTP/1.1"):
-            self.close_connection = 0
+            self.close_connection = False
         # Examine the headers and look for an Expect directive
         expect = self.headers.get('Expect', "")
         if (expect.lower() == "100-continue" and
@@ -388,7 +388,7 @@
                 self.send_error(HTTPStatus.REQUEST_URI_TOO_LONG)
                 return
             if not self.raw_requestline:
-                self.close_connection = 1
+                self.close_connection = True
                 return
             if not self.parse_request():
                 # An error code has been sent, just exit
@@ -405,12 +405,12 @@
         except socket.timeout as e:
             #a read or a write timed out.  Discard this connection
             self.log_error("Request timed out: %r", e)
-            self.close_connection = 1
+            self.close_connection = True
             return
 
     def handle(self):
         """Handle multiple requests if necessary."""
-        self.close_connection = 1
+        self.close_connection = True
 
         self.handle_one_request()
         while not self.close_connection:
@@ -496,9 +496,9 @@
 
         if keyword.lower() == 'connection':
             if value.lower() == 'close':
-                self.close_connection = 1
+                self.close_connection = True
             elif value.lower() == 'keep-alive':
-                self.close_connection = 0
+                self.close_connection = False
 
     def end_headers(self):
         """Send the blank line ending the MIME headers."""
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
@@ -616,6 +616,11 @@
         self.verify_expected_headers(result[1:-1])
         self.verify_get_called()
         self.assertEqual(result[-1], b'<html><body>Data</body></html>\r\n')
+        self.assertEqual(self.handler.requestline, 'GET / HTTP/1.1')
+        self.assertEqual(self.handler.command, 'GET')
+        self.assertEqual(self.handler.path, '/')
+        self.assertEqual(self.handler.request_version, 'HTTP/1.1')
+        self.assertSequenceEqual(self.handler.headers.items(), ())
 
     def test_http_1_0(self):
         result = self.send_typical_request(b'GET / HTTP/1.0\r\n\r\n')
@@ -623,6 +628,11 @@
         self.verify_expected_headers(result[1:-1])
         self.verify_get_called()
         self.assertEqual(result[-1], b'<html><body>Data</body></html>\r\n')
+        self.assertEqual(self.handler.requestline, 'GET / HTTP/1.0')
+        self.assertEqual(self.handler.command, 'GET')
+        self.assertEqual(self.handler.path, '/')
+        self.assertEqual(self.handler.request_version, 'HTTP/1.0')
+        self.assertSequenceEqual(self.handler.headers.items(), ())
 
     def test_http_0_9(self):
         result = self.send_typical_request(b'GET / HTTP/0.9\r\n\r\n')
@@ -636,6 +646,12 @@
         self.verify_expected_headers(result[1:-1])
         self.verify_get_called()
         self.assertEqual(result[-1], b'<html><body>Data</body></html>\r\n')
+        self.assertEqual(self.handler.requestline, 'GET / HTTP/1.0')
+        self.assertEqual(self.handler.command, 'GET')
+        self.assertEqual(self.handler.path, '/')
+        self.assertEqual(self.handler.request_version, 'HTTP/1.0')
+        headers = (("Expect", "100-continue"),)
+        self.assertSequenceEqual(self.handler.headers.items(), headers)
 
     def test_with_continue_1_1(self):
         result = self.send_typical_request(b'GET / HTTP/1.1\r\nExpect: 100-continue\r\n\r\n')
@@ -645,6 +661,12 @@
         self.verify_expected_headers(result[2:-1])
         self.verify_get_called()
         self.assertEqual(result[-1], b'<html><body>Data</body></html>\r\n')
+        self.assertEqual(self.handler.requestline, 'GET / HTTP/1.1')
+        self.assertEqual(self.handler.command, 'GET')
+        self.assertEqual(self.handler.path, '/')
+        self.assertEqual(self.handler.request_version, 'HTTP/1.1')
+        headers = (("Expect", "100-continue"),)
+        self.assertSequenceEqual(self.handler.headers.items(), headers)
 
     def test_header_buffering_of_send_error(self):
 
@@ -730,6 +752,7 @@
         result = self.send_typical_request(b'GET ' + b'x' * 65537)
         self.assertEqual(result[0], b'HTTP/1.1 414 Request-URI Too Long\r\n')
         self.assertFalse(self.handler.get_called)
+        self.assertIsInstance(self.handler.requestline, str)
 
     def test_header_length(self):
         # Issue #6791: same for headers
@@ -737,6 +760,22 @@
             b'GET / HTTP/1.1\r\nX-Foo: bar' + b'r' * 65537 + b'\r\n\r\n')
         self.assertEqual(result[0], b'HTTP/1.1 400 Line too long\r\n')
         self.assertFalse(self.handler.get_called)
+        self.assertEqual(self.handler.requestline, 'GET / HTTP/1.1')
+
+    def test_close_connection(self):
+        # handle_one_request() should be repeatedly called until
+        # it sets close_connection
+        def handle_one_request():
+            self.handler.close_connection = next(close_values)
+        self.handler.handle_one_request = handle_one_request
+
+        close_values = iter((True,))
+        self.handler.handle()
+        self.assertRaises(StopIteration, next, close_values)
+
+        close_values = iter((False, False, True))
+        self.handler.handle()
+        self.assertRaises(StopIteration, next, close_values)
 
 class SimpleHTTPRequestHandlerTestCase(unittest.TestCase):
     """ Test url parsing """

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


More information about the Python-checkins mailing list