Define a set of HTTPStatus subclasses that can be raised to perform various types of HTTP redirects. This should avoid the problem of hooks and responder methods possibly overriding the redirect. Raising an instance of one of these classes and will short-circuit request processing similar to raising an instance of HTTPError. Specifically, if raised in a before hook, it will skip any remaining hooks and the responder method, but will not skip any process_response middleware methods. If raised within a responder, it will skip the rest of the responder and all after hooks. If raised in an after hook, it would skip remaining after hooks but not middleware methods. And finally, if raised within a middleware method, execution would perceive as described at the bottom of [1]. The above behavior is inherited from HTTPStatus and so is not re-tested in the subclasses. [1]: https://falcon.readthedocs.org/en/stable/api/middleware.html Closes #406
50 lines
1.4 KiB
Python
50 lines
1.4 KiB
Python
import ddt
|
|
|
|
import falcon.testing as testing
|
|
import falcon
|
|
|
|
|
|
class RedirectingResource(object):
|
|
|
|
# NOTE(kgriffs): You wouldn't necessarily use these types of
|
|
# http methods with these types of redirects; this is only
|
|
# done to simplify testing.
|
|
|
|
def on_get(self, req, resp):
|
|
raise falcon.HTTPMovedPermanently('/moved/perm')
|
|
|
|
def on_post(self, req, resp):
|
|
raise falcon.HTTPFound('/found')
|
|
|
|
def on_put(self, req, resp):
|
|
raise falcon.HTTPSeeOther('/see/other')
|
|
|
|
def on_delete(self, req, resp):
|
|
raise falcon.HTTPTemporaryRedirect('/tmp/redirect')
|
|
|
|
def on_head(self, req, resp):
|
|
raise falcon.HTTPPermanentRedirect('/perm/redirect')
|
|
|
|
|
|
@ddt.ddt
|
|
class TestRedirects(testing.TestBase):
|
|
|
|
def before(self):
|
|
self.api.add_route('/', RedirectingResource())
|
|
|
|
@ddt.data(
|
|
('GET', falcon.HTTP_301, '/moved/perm'),
|
|
('POST', falcon.HTTP_302, '/found'),
|
|
('PUT', falcon.HTTP_303, '/see/other'),
|
|
('DELETE', falcon.HTTP_307, '/tmp/redirect'),
|
|
('HEAD', falcon.HTTP_308, '/perm/redirect'),
|
|
)
|
|
@ddt.unpack
|
|
def test_redirect(self, method, expected_status, expected_location):
|
|
result = self.simulate_request('/', method=method)
|
|
|
|
self.assertEqual(result, [])
|
|
self.assertEqual(self.srmock.status, expected_status)
|
|
self.assertEqual(self.srmock.headers_dict['location'],
|
|
expected_location)
|