summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Petrello <lists@ryanpetrello.com>2014-06-26 10:11:44 -0400
committerRyan Petrello <lists@ryanpetrello.com>2014-06-26 10:22:08 -0400
commit63d9d3d8fdab69323010ace0f05ddfe10cae41f1 (patch)
tree822f164cd6ce7c6cba6f4f774dd251aa7824edaa
parent7d5b94e2f68aa254d4905e90572aa7dc5e04ab28 (diff)
downloadpecan-63d9d3d8fdab69323010ace0f05ddfe10cae41f1.tar.gz
For an HTTP 405 on generic methods, attempt to specify an Allow header.
Change-Id: I726d698fc014c21cc1e43a09a129384fa1f1235f
-rw-r--r--pecan/core.py6
-rw-r--r--pecan/decorators.py2
-rw-r--r--pecan/tests/test_generic.py25
3 files changed, 32 insertions, 1 deletions
diff --git a/pecan/core.py b/pecan/core.py
index a43f3de..fae1502 100644
--- a/pecan/core.py
+++ b/pecan/core.py
@@ -631,6 +631,12 @@ class PecanBase(object):
else:
if not isinstance(e, exc.HTTPException):
raise
+
+ # if this is an HTTP 405, attempt to specify an Allow header
+ if isinstance(e, exc.HTTPMethodNotAllowed) and controller:
+ allowed_methods = _cfg(controller).get('allowed_methods', [])
+ if allowed_methods:
+ state.response.allow = sorted(allowed_methods)
finally:
# handle "after" hooks
self.handle_hooks(
diff --git a/pecan/decorators.py b/pecan/decorators.py
index f40d16a..45ad635 100644
--- a/pecan/decorators.py
+++ b/pecan/decorators.py
@@ -16,6 +16,7 @@ def when_for(controller):
expose(**kw)(f)
_cfg(f)['generic_handler'] = True
controller._pecan['generic_handlers'][method.upper()] = f
+ controller._pecan['allowed_methods'].append(method.upper())
return f
return decorate
return when
@@ -56,6 +57,7 @@ def expose(template=None,
if generic:
cfg['generic'] = True
cfg['generic_handlers'] = dict(DEFAULT=f)
+ cfg['allowed_methods'] = []
f.when = when_for(f)
# store the arguments for this controller method
diff --git a/pecan/tests/test_generic.py b/pecan/tests/test_generic.py
index 879ad26..453f123 100644
--- a/pecan/tests/test_generic.py
+++ b/pecan/tests/test_generic.py
@@ -6,7 +6,7 @@ except:
from six import b as b_
-from pecan import Pecan, expose
+from pecan import Pecan, expose, abort
from pecan.tests import PecanTestCase
@@ -37,3 +37,26 @@ class TestGeneric(PecanTestCase):
r = app.get('/do_get', status=404)
assert r.status_int == 404
+
+ def test_generic_allow_header(self):
+ class RootController(object):
+ @expose(generic=True)
+ def index(self):
+ abort(405)
+
+ @index.when(method='POST', template='json')
+ def do_post(self):
+ return dict(result='POST')
+
+ @index.when(method='GET')
+ def do_get(self):
+ return 'GET'
+
+ @index.when(method='PATCH')
+ def do_patch(self):
+ return 'PATCH'
+
+ app = TestApp(Pecan(RootController()))
+ r = app.delete('/', expect_errors=True)
+ assert r.status_int == 405
+ assert r.headers['Allow'] == 'GET, PATCH, POST'