Index: Lib/http/server.py =================================================================== --- Lib/http/server.py (revision 86610) +++ Lib/http/server.py (working copy) @@ -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. Index: Lib/test/test_httpservers.py =================================================================== --- Lib/test/test_httpservers.py (revision 86595) +++ Lib/test/test_httpservers.py (working copy) @@ -476,6 +476,28 @@ match = self.HTTPResponseMatch.search(response) self.assertTrue(match is not None) + 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_http_1_1(self): result = self.send_typical_request(b'GET / HTTP/1.1\r\n\r\n') self.verify_http_server_response(result[0])