Add new exception tornado.web.Finish to quietly end a request.
This allows error pages to be generated inline with the main code instead of in write_error and is friendlier to generating error pages from library code. Closes #1064.
This commit is contained in:
parent
2cec3195f2
commit
596038c284
|
@ -235,6 +235,7 @@
|
|||
Everything else
|
||||
---------------
|
||||
.. autoexception:: HTTPError
|
||||
.. autoexception:: Finish
|
||||
.. autoexception:: MissingArgumentError
|
||||
.. autoclass:: UIModule
|
||||
:members:
|
||||
|
|
|
@ -10,7 +10,7 @@ from tornado.template import DictLoader
|
|||
from tornado.testing import AsyncHTTPTestCase, ExpectLog, gen_test
|
||||
from tornado.test.util import unittest
|
||||
from tornado.util import u, bytes_type, ObjectDict, unicode_type
|
||||
from tornado.web import RequestHandler, authenticated, Application, asynchronous, url, HTTPError, StaticFileHandler, _create_signature_v1, create_signed_value, decode_signed_value, ErrorHandler, UIModule, MissingArgumentError, stream_request_body
|
||||
from tornado.web import RequestHandler, authenticated, Application, asynchronous, url, HTTPError, StaticFileHandler, _create_signature_v1, create_signed_value, decode_signed_value, ErrorHandler, UIModule, MissingArgumentError, stream_request_body, Finish
|
||||
|
||||
import binascii
|
||||
import contextlib
|
||||
|
@ -2307,3 +2307,20 @@ class XSRFTest(SimpleHandlerTestCase):
|
|||
body=urllib_parse.urlencode(dict(_xsrf=body_token)),
|
||||
headers=self.cookie_headers(cookie_token))
|
||||
self.assertEqual(response.code, 200)
|
||||
|
||||
|
||||
@wsgi_safe
|
||||
class FinishExceptionTest(SimpleHandlerTestCase):
|
||||
class Handler(RequestHandler):
|
||||
def get(self):
|
||||
self.set_status(401)
|
||||
self.set_header('WWW-Authenticate', 'Basic realm="something"')
|
||||
self.write('authentication required')
|
||||
raise Finish()
|
||||
|
||||
def test_finish_exception(self):
|
||||
response = self.fetch('/')
|
||||
self.assertEqual(response.code, 401)
|
||||
self.assertEqual('Basic realm="something"',
|
||||
response.headers.get('WWW-Authenticate'))
|
||||
self.assertEqual(b'authentication required', response.body)
|
||||
|
|
|
@ -1384,6 +1384,11 @@ class RequestHandler(object):
|
|||
" (" + self.request.remote_ip + ")"
|
||||
|
||||
def _handle_request_exception(self, e):
|
||||
if isinstance(e, Finish):
|
||||
# Not an error; just finish the request without logging.
|
||||
if not self._finished:
|
||||
self.finish()
|
||||
return
|
||||
self.log_exception(*sys.exc_info())
|
||||
if self._finished:
|
||||
# Extra errors after the request has been finished should
|
||||
|
@ -1938,6 +1943,9 @@ class HTTPError(Exception):
|
|||
`RequestHandler.send_error` since it automatically ends the
|
||||
current function.
|
||||
|
||||
To customize the response sent with an `HTTPError`, override
|
||||
`RequestHandler.write_error`.
|
||||
|
||||
:arg int status_code: HTTP status code. Must be listed in
|
||||
`httplib.responses <http.client.responses>` unless the ``reason``
|
||||
keyword argument is given.
|
||||
|
@ -1966,6 +1974,25 @@ class HTTPError(Exception):
|
|||
return message
|
||||
|
||||
|
||||
class Finish(Exception):
|
||||
"""An exception that ends the request without producing an error response.
|
||||
|
||||
When `Finish` is raised in a `RequestHandler`, the request will end
|
||||
(calling `RequestHandler.finish` if it hasn't already been called),
|
||||
but the outgoing response will not be modified and the error-handling
|
||||
methods (including `RequestHandler.write_error`) will not be called.
|
||||
|
||||
This can be a more convenient way to implement custom error pages
|
||||
than overriding ``write_error`` (especially in library code)::
|
||||
|
||||
if self.current_user is None:
|
||||
self.set_status(401)
|
||||
self.set_header('WWW-Authenticate', 'Basic realm="something"')
|
||||
raise Finish()
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class MissingArgumentError(HTTPError):
|
||||
"""Exception raised by `RequestHandler.get_argument`.
|
||||
|
||||
|
|
Loading…
Reference in New Issue