For an HTTP 405 on generic methods, attempt to specify an Allow header.

Change-Id: I726d698fc014c21cc1e43a09a129384fa1f1235f
This commit is contained in:
Ryan Petrello
2014-06-26 10:11:44 -04:00
parent 7d5b94e2f6
commit 63d9d3d8fd
3 changed files with 32 additions and 1 deletions

View File

@@ -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(

View File

@@ -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

View File

@@ -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'