changeset: 101787:b1041ddb1391 branch: 2.7 parent: 101784:b86e259271b3 user: Martin Panter date: Wed Jun 08 07:16:14 2016 +0000 files: Doc/library/basehttpserver.rst Lib/BaseHTTPServer.py Lib/test/test_httpservers.py Misc/ACKS Misc/NEWS description: Issue #25738: Don’t send message body for 205 Reset Content Patch by Susumu Koshiba. diff -r b86e259271b3 -r b1041ddb1391 Doc/library/basehttpserver.rst --- a/Doc/library/basehttpserver.rst Wed Jun 08 06:12:22 2016 +0000 +++ b/Doc/library/basehttpserver.rst Wed Jun 08 07:16:14 2016 +0000 @@ -197,7 +197,10 @@ Sends and logs a complete error reply to the client. The numeric *code* specifies the HTTP error code, with *message* as optional, more specific text. A complete set of headers is sent, followed by text composed using the - :attr:`error_message_format` class variable. + :attr:`error_message_format` class variable. The body will be empty + if the method is HEAD or the response code is one of the following: + ``1xx``, ``204 No Content``, ``205 Reset Content``, + ``304 Not Modified``. .. method:: send_response(code[, message]) diff -r b86e259271b3 -r b1041ddb1391 Lib/BaseHTTPServer.py --- a/Lib/BaseHTTPServer.py Wed Jun 08 06:12:22 2016 +0000 +++ b/Lib/BaseHTTPServer.py Wed Jun 08 07:16:14 2016 +0000 @@ -362,14 +362,25 @@ message = short explain = long self.log_error("code %d, message %s", code, message) - # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201) - content = (self.error_message_format % - {'code': code, 'message': _quote_html(message), 'explain': explain}) self.send_response(code, message) - self.send_header("Content-Type", self.error_content_type) self.send_header('Connection', 'close') + + # Message body is omitted for cases described in: + # - RFC7230: 3.3. 1xx, 204(No Content), 304(Not Modified) + # - RFC7231: 6.3.6. 205(Reset Content) + content = None + if code >= 200 and code not in (204, 205, 304): + # HTML encode to prevent Cross Site Scripting attacks + # (see bug #1100201) + content = (self.error_message_format % { + 'code': code, + 'message': _quote_html(message), + 'explain': explain + }) + self.send_header("Content-Type", self.error_content_type) self.end_headers() - if self.command != 'HEAD' and code >= 200 and code not in (204, 304): + + if self.command != 'HEAD' and content: self.wfile.write(content) error_message_format = DEFAULT_ERROR_MESSAGE diff -r b86e259271b3 -r b1041ddb1391 Lib/test/test_httpservers.py --- a/Lib/test/test_httpservers.py Wed Jun 08 06:12:22 2016 +0000 +++ b/Lib/test/test_httpservers.py Wed Jun 08 07:16:14 2016 +0000 @@ -178,6 +178,12 @@ self.send_header('Connection', 'close') self.end_headers() + def do_SEND_ERROR(self): + self.send_error(int(self.path[1:])) + + def do_HEAD(self): + self.send_error(int(self.path[1:])) + def setUp(self): BaseTestCase.setUp(self) self.con = httplib.HTTPConnection('localhost', self.PORT) @@ -276,6 +282,38 @@ res = self.con.getresponse() self.assertEqual(res.status, 999) + def test_send_error(self): + allow_transfer_encoding_codes = (205, 304) + for code in (101, 102, 204, 205, 304): + self.con.request('SEND_ERROR', '/{}'.format(code)) + res = self.con.getresponse() + self.assertEqual(code, res.status) + self.assertEqual(None, res.getheader('Content-Length')) + self.assertEqual(None, res.getheader('Content-Type')) + if code not in allow_transfer_encoding_codes: + self.assertEqual(None, res.getheader('Transfer-Encoding')) + + data = res.read() + self.assertEqual(b'', data) + + def test_head_via_send_error(self): + allow_transfer_encoding_codes = (205, 304) + for code in (101, 200, 204, 205, 304): + self.con.request('HEAD', '/{}'.format(code)) + res = self.con.getresponse() + self.assertEqual(code, res.status) + if code == 200: + self.assertEqual(None, res.getheader('Content-Length')) + self.assertIn('text/html', res.getheader('Content-Type')) + else: + self.assertEqual(None, res.getheader('Content-Length')) + self.assertEqual(None, res.getheader('Content-Type')) + if code not in allow_transfer_encoding_codes: + self.assertEqual(None, res.getheader('Transfer-Encoding')) + + data = res.read() + self.assertEqual(b'', data) + class SimpleHTTPServerTestCase(BaseTestCase): class request_handler(NoLogRequestHandler, SimpleHTTPRequestHandler): diff -r b86e259271b3 -r b1041ddb1391 Misc/ACKS --- a/Misc/ACKS Wed Jun 08 06:12:22 2016 +0000 +++ b/Misc/ACKS Wed Jun 08 07:16:14 2016 +0000 @@ -741,6 +741,7 @@ Марк Коренберг Vlad Korolev Anna Koroliuk +Susumu Koshiba Joseph Koshy Daniel Kozan Jerzy Kozera diff -r b86e259271b3 -r b1041ddb1391 Misc/NEWS --- a/Misc/NEWS Wed Jun 08 06:12:22 2016 +0000 +++ b/Misc/NEWS Wed Jun 08 07:16:14 2016 +0000 @@ -92,6 +92,11 @@ Library ------- +- Issue #25738: Stop BaseHTTPServer.BaseHTTPRequestHandler.send_error() from + sending a message body for 205 Reset Content. Also, don't send the + Content-Type header field in responses that don't have a body. Based on + patch by Susumu Koshiba. + - Issue #21313: Fix the "platform" module to tolerate when sys.version contains truncated build information.