Kaydet (Commit) 2688644e authored tarafından Senthil Kumaran's avatar Senthil Kumaran

#1291 http.server's send_error takes an optional explain argument

üst 12bb353d
...@@ -170,15 +170,19 @@ of which this module provides three different variants: ...@@ -170,15 +170,19 @@ of which this module provides three different variants:
.. versionadded:: 3.2 .. versionadded:: 3.2
.. method:: send_error(code, message=None) .. method:: send_error(code, message=None, explain=None)
Sends and logs a complete error reply to the client. The numeric *code* 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 specifies the HTTP error code, with *message* as optional, more specific
complete set of headers is sent, followed by text composed using the text, usually referring to short message response. The *explain*
:attr:`error_message_format` class variable. argument can be used to send a detailed information about the error in
response content body. A complete set of headers is sent, followed by
text composed using the :attr:`error_message_format` class variable.
.. versionchanged:: 3.4 .. versionchanged:: 3.4
The error response includes a Content-Length header. The error response includes a Content-Length header.
explain argument was added.
.. method:: send_response(code, message=None) .. method:: send_response(code, message=None)
......
...@@ -401,12 +401,17 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler): ...@@ -401,12 +401,17 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler):
while not self.close_connection: while not self.close_connection:
self.handle_one_request() self.handle_one_request()
def send_error(self, code, message=None): def send_error(self, code, message=None, explain=None):
"""Send and log an error reply. """Send and log an error reply.
Arguments are the error code, and a detailed message. Arguments are
The detailed message defaults to the short entry matching the * code: an HTTP error code
response code. 3 digits
* message: a simple optional 1 line reason phrase.
*( HTAB / SP / VCHAR / %x80-FF )
defaults to short entry matching the response code
* explain: a detailed message defaults to the long entry
matching the response code.
This sends an error response (so it must be called before any This sends an error response (so it must be called before any
output has been generated), logs the error, and finally sends output has been generated), logs the error, and finally sends
...@@ -420,11 +425,12 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler): ...@@ -420,11 +425,12 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler):
shortmsg, longmsg = '???', '???' shortmsg, longmsg = '???', '???'
if message is None: if message is None:
message = shortmsg message = shortmsg
explain = longmsg if explain is None:
explain = longmsg
self.log_error("code %d, message %s", code, message) self.log_error("code %d, message %s", code, message)
# using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201) # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201)
content = (self.error_message_format % content = (self.error_message_format %
{'code': code, 'message': _quote_html(message), 'explain': explain}) {'code': code, 'message': _quote_html(message), 'explain': _quote_html(explain)})
body = content.encode('UTF-8', 'replace') body = content.encode('UTF-8', 'replace')
self.send_response(code, message) self.send_response(code, message)
self.send_header("Content-Type", self.error_content_type) self.send_header("Content-Type", self.error_content_type)
......
...@@ -95,6 +95,10 @@ class BaseHTTPServerTestCase(BaseTestCase): ...@@ -95,6 +95,10 @@ class BaseHTTPServerTestCase(BaseTestCase):
def do_NOTFOUND(self): def do_NOTFOUND(self):
self.send_error(404) self.send_error(404)
def do_EXPLAINERROR(self):
self.send_error(999, "Short Message",
"This is a long \n explaination")
def do_CUSTOM(self): def do_CUSTOM(self):
self.send_response(999) self.send_response(999)
self.send_header('Content-Type', 'text/html') self.send_header('Content-Type', 'text/html')
...@@ -206,6 +210,12 @@ class BaseHTTPServerTestCase(BaseTestCase): ...@@ -206,6 +210,12 @@ class BaseHTTPServerTestCase(BaseTestCase):
res = self.con.getresponse() res = self.con.getresponse()
self.assertEqual(res.status, 999) self.assertEqual(res.status, 999)
def test_return_explain_error(self):
self.con.request('EXPLAINERROR', '/')
res = self.con.getresponse()
self.assertEqual(res.status, 999)
self.assertTrue(int(res.getheader('Content-Length')))
def test_latin1_header(self): def test_latin1_header(self):
self.con.request('LATINONEHEADER', '/', headers={ self.con.request('LATINONEHEADER', '/', headers={
'X-Special-Incoming': 'Ärger mit Unicode' 'X-Special-Incoming': 'Ärger mit Unicode'
......
...@@ -280,6 +280,9 @@ Core and Builtins ...@@ -280,6 +280,9 @@ Core and Builtins
Library Library
------- -------
- Issue #12921: http.server's send_error takes an explain argument to send more
information in response. Patch contributed by Karl.
- Issue #17414: Add timeit, repeat, and default_timer to timeit.__all__. - Issue #17414: Add timeit, repeat, and default_timer to timeit.__all__.
- Issue #1285086: Get rid of the refcounting hack and speed up - Issue #1285086: Get rid of the refcounting hack and speed up
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment