[Python-checkins] r86640 - in python/branches/py3k: Doc/library/http.server.rst Lib/http/server.py Lib/test/test_httpservers.py Misc/NEWS

senthil.kumaran python-checkins at python.org
Sun Nov 21 15:36:14 CET 2010


Author: senthil.kumaran
Date: Sun Nov 21 15:36:14 2010
New Revision: 86640

Log:
Fix issue3709 - BaseHTTPRequestHandler will buffer the headers and write only on end_headers call.



Modified:
   python/branches/py3k/Doc/library/http.server.rst
   python/branches/py3k/Lib/http/server.py
   python/branches/py3k/Lib/test/test_httpservers.py
   python/branches/py3k/Misc/NEWS

Modified: python/branches/py3k/Doc/library/http.server.rst
==============================================================================
--- python/branches/py3k/Doc/library/http.server.rst	(original)
+++ python/branches/py3k/Doc/library/http.server.rst	Sun Nov 21 15:36:14 2010
@@ -182,22 +182,29 @@
 
    .. method:: send_header(keyword, value)
 
-      Writes a specific HTTP header to the output stream. *keyword* should
-      specify the header keyword, with *value* specifying its value.
+      Stores the HTTP header to an internal buffer which will be written to the
+      output stream when :meth:`end_headers` method is invoked.
+      *keyword* should specify the header keyword, with *value*
+      specifying its value.
+
+      .. versionchanged:: 3.2 Storing the headers in an internal buffer
+
 
    .. method:: send_response_only(code, message=None)
 
       Sends the reponse header only, used for the purposes when ``100
-      Continue`` response is sent by the server to the client. If the *message*
-      is not specified, the HTTP message corresponding the response *code*  is
-      sent.
+      Continue`` response is sent by the server to the client. The headers not
+      buffered and sent directly the output stream.If the *message* is not
+      specified, the HTTP message corresponding the response *code*  is sent.
 
       .. versionadded:: 3.2
 
    .. method:: end_headers()
 
-      Sends a blank line, indicating the end of the HTTP headers in the
-      response.
+      Write the buffered HTTP headers to the output stream and send a blank
+      line, indicating the end of the HTTP headers in the response.
+
+      .. versionchanged:: 3.2 Writing the buffered headers to the output stream.
 
    .. method:: log_request(code='-', size='-')
 

Modified: python/branches/py3k/Lib/http/server.py
==============================================================================
--- python/branches/py3k/Lib/http/server.py	(original)
+++ python/branches/py3k/Lib/http/server.py	Sun Nov 21 15:36:14 2010
@@ -443,7 +443,10 @@
     def send_header(self, keyword, value):
         """Send a MIME header."""
         if self.request_version != 'HTTP/0.9':
-            self.wfile.write(("%s: %s\r\n" % (keyword, value)).encode('ASCII', 'strict'))
+            if not hasattr(self, '_headers_buffer'):
+                self._headers_buffer = []
+            self._headers_buffer.append(
+                ("%s: %s\r\n" % (keyword, value)).encode('ASCII', 'strict'))
 
         if keyword.lower() == 'connection':
             if value.lower() == 'close':
@@ -454,7 +457,9 @@
     def end_headers(self):
         """Send the blank line ending the MIME headers."""
         if self.request_version != 'HTTP/0.9':
-            self.wfile.write(b"\r\n")
+            self._headers_buffer.append(b"\r\n")
+            self.wfile.write(b"".join(self._headers_buffer))
+            self._headers_buffer = []
 
     def log_request(self, code='-', size='-'):
         """Log an accepted request.

Modified: python/branches/py3k/Lib/test/test_httpservers.py
==============================================================================
--- python/branches/py3k/Lib/test/test_httpservers.py	(original)
+++ python/branches/py3k/Lib/test/test_httpservers.py	Sun Nov 21 15:36:14 2010
@@ -511,6 +511,49 @@
         self.verify_get_called()
         self.assertEqual(result[-1], b'<html><body>Data</body></html>\r\n')
 
+    def test_header_buffering(self):
+
+        def _readAndReseek(f):
+            pos = f.tell()
+            f.seek(0)
+            data = f.read()
+            f.seek(pos)
+            return data
+
+        input = BytesIO(b'GET / HTTP/1.1\r\n\r\n')
+        output = BytesIO()
+        self.handler.rfile = input
+        self.handler.wfile = output
+        self.handler.request_version = 'HTTP/1.1'
+
+        self.handler.send_header('Foo', 'foo')
+        self.handler.send_header('bar', 'bar')
+        self.assertEqual(_readAndReseek(output), b'')
+        self.handler.end_headers()
+        self.assertEqual(_readAndReseek(output),
+                         b'Foo: foo\r\nbar: bar\r\n\r\n')
+
+    def test_header_unbuffered_when_continue(self):
+
+        def _readAndReseek(f):
+            pos = f.tell()
+            f.seek(0)
+            data = f.read()
+            f.seek(pos)
+            return data
+
+        input = BytesIO(b'GET / HTTP/1.1\r\nExpect: 100-continue\r\n\r\n')
+        output = BytesIO()
+        self.handler.rfile = input
+        self.handler.wfile = output
+        self.handler.request_version = 'HTTP/1.1'
+
+        self.handler.handle_one_request()
+        self.assertNotEqual(_readAndReseek(output), b'')
+        result = _readAndReseek(output).split(b'\r\n')
+        self.assertEqual(result[0], b'HTTP/1.1 100 Continue')
+        self.assertEqual(result[1], b'HTTP/1.1 200 OK')
+
     def test_with_continue_rejected(self):
         usual_handler = self.handler        # Save to avoid breaking any subsequent tests.
         self.handler = RejectingSocketlessRequestHandler()

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Sun Nov 21 15:36:14 2010
@@ -32,6 +32,10 @@
 Library
 -------
 
+- Issue #3709: BaseHTTPRequestHandler will buffer the headers and write to
+  output stream only when end_headers is invoked. This is a speedup and an
+  internal optimization.  Patch by endian.
+
 - Issue #10220: Added inspect.getgeneratorstate. Initial patch by
   Rodolpho Eckhardt.
 


More information about the Python-checkins mailing list