Files
deb-python-falcon/tests/test_after_hooks.py
kgriffs 9a22f69e73 fix(Response): Headers are case-sensitive
Web developers tend to think of headers being case-insensitive. However,
if you try to set the same header twice, with differently-cased header
names, Falcon treated them as separate headers.

This patch changes falcon.Request such that it now normalizes header
names internally, and when performing lookups.

Applications shouldn't break due to this change unless they were
accessing the private req._headers attribute directly.

Closes #185
2014-01-02 12:45:58 -06:00

151 lines
4.2 KiB
Python

import json
import falcon
import falcon.testing as testing
def validate_output(req, resp):
raise falcon.HTTPError(falcon.HTTP_723, title=None)
def serialize_body(req, resp):
body = resp.body
if body is not None:
resp.body = json.dumps(body)
else:
resp.body = 'Nothing to see here. Move along.'
def fluffiness(req, resp):
resp.body = 'fluffy'
def cuteness(req, resp):
if resp.body == 'fluffy':
resp.body += ' and cute'
class WrappedRespondersResource(object):
@falcon.after(serialize_body)
@falcon.after(validate_output)
def on_get(self, req, resp):
self.req = req
self.resp = resp
@falcon.after(serialize_body)
def on_put(self, req, resp):
self.req = req
self.resp = resp
resp.body = {'animal': 'falcon'}
@falcon.after(cuteness)
@falcon.after(fluffiness)
class WrappedClassResource(object):
# Test that the decorator skips non-callables
on_post = False
def __init__(self):
# Test that the decorator skips non-callables
self.on_patch = []
def on_get(self, req, resp):
self.req = req
self.resp = resp
def on_head(self, req, resp):
self.req = req
self.resp = resp
class ZooResource(object):
def on_get(self, req, resp):
self.resp = resp
class SingleResource(object):
def on_options(self, req, resp):
resp.status = falcon.HTTP_501
class TestHooks(testing.TestBase):
def before(self):
self.resource = WrappedRespondersResource()
self.api.add_route(self.test_route, self.resource)
self.wrapped_resource = WrappedClassResource()
self.api.add_route('/wrapped', self.wrapped_resource)
def test_global_hook(self):
self.assertRaises(TypeError, falcon.API, None, {})
self.assertRaises(TypeError, falcon.API, None, 0)
self.api = falcon.API(after=fluffiness)
zoo_resource = ZooResource()
self.api.add_route(self.test_route, zoo_resource)
self.simulate_request(self.test_route)
self.assertEqual(b'fluffy', zoo_resource.resp.body_encoded)
# hook does not affect the default on_options
body = self.simulate_request(self.test_route, method='OPTIONS')
self.assertEqual(falcon.HTTP_204, self.srmock.status)
self.assertEqual([], body)
def test_multiple_global_hook(self):
self.api = falcon.API(after=[fluffiness, cuteness])
zoo_resource = ZooResource()
self.api.add_route(self.test_route, zoo_resource)
self.simulate_request(self.test_route)
self.assertEqual(b'fluffy and cute', zoo_resource.resp.body_encoded)
def test_output_validator(self):
self.simulate_request(self.test_route)
self.assertEqual(falcon.HTTP_723, self.srmock.status)
self.assertEqual(None, self.resource.resp.body_encoded)
def test_serializer(self):
self.simulate_request(self.test_route, method='PUT')
actual_body = self.resource.resp.body_encoded
self.assertEqual(b'{"animal": "falcon"}', actual_body)
def test_wrapped_resource(self):
expected = b'fluffy and cute'
self.simulate_request('/wrapped')
self.assertEqual(falcon.HTTP_200, self.srmock.status)
self.assertEqual(expected, self.wrapped_resource.resp.body_encoded)
self.simulate_request('/wrapped', method='HEAD')
self.assertEqual(falcon.HTTP_200, self.srmock.status)
self.simulate_request('/wrapped', method='POST')
self.assertEqual(falcon.HTTP_405, self.srmock.status)
self.simulate_request('/wrapped', method='PATCH')
self.assertEqual(falcon.HTTP_405, self.srmock.status)
# decorator does not affect the default on_options
body = self.simulate_request('/wrapped', method='OPTIONS')
self.assertEqual(falcon.HTTP_204, self.srmock.status)
self.assertEqual([], body)
def test_customized_options(self):
self.api = falcon.API(after=fluffiness)
self.api.add_route('/one', SingleResource())
body = self.simulate_request('/one', method='OPTIONS')
self.assertEqual(falcon.HTTP_501, self.srmock.status)
self.assertEqual([b'fluffy'], body)
self.assertNotIn('allow', self.srmock.headers_dict)