summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Petrello <lists@ryanpetrello.com>2014-04-23 15:18:37 -0700
committerRyan Petrello <lists@ryanpetrello.com>2014-04-23 15:35:30 -0700
commit7e6e3fc8766d6331165e1a06f163a90e579b1d03 (patch)
treeb2a9d88eff89db6a61f762379bd5a39098699547
parent5ede5e03572c873ff533ef9c2c0db5f92a8bc6ce (diff)
downloadpecan-7e6e3fc8766d6331165e1a06f163a90e579b1d03.tar.gz
Work around another obscure RestController edge case that should raise a 404.
Fixes bug 1311147 Change-Id: I3dd0986c458902b03ed140872fc1938b06e75f4b
-rw-r--r--pecan/rest.py6
-rw-r--r--pecan/tests/test_rest.py43
2 files changed, 49 insertions, 0 deletions
diff --git a/pecan/rest.py b/pecan/rest.py
index 881de79..db955c5 100644
--- a/pecan/rest.py
+++ b/pecan/rest.py
@@ -176,6 +176,12 @@ class RestController(object):
if not remainder or remainder == ['']:
controller = self._find_controller('get_all', 'get')
if controller:
+ argspec = getargspec(controller)
+ fixed_args = len(argspec.args[1:]) - len(
+ request.pecan.get('routing_args', [])
+ )
+ if len(remainder) < fixed_args:
+ abort(404)
return controller, []
abort(404)
diff --git a/pecan/tests/test_rest.py b/pecan/tests/test_rest.py
index ab088f2..7e1e8b6 100644
--- a/pecan/tests/test_rest.py
+++ b/pecan/tests/test_rest.py
@@ -741,6 +741,49 @@ class TestRestController(PecanTestCase):
r = app.request('/things', method='RESET', status=404)
assert r.status_int == 404
+ def test_nested_rest_with_missing_intermediate_id(self):
+
+ class BarsController(RestController):
+
+ data = [['zero-zero', 'zero-one'], ['one-zero', 'one-one']]
+
+ @expose('json')
+ def get_all(self, foo_id):
+ return dict(items=self.data[int(foo_id)])
+
+ class FoosController(RestController):
+
+ data = ['zero', 'one']
+
+ bars = BarsController()
+
+ @expose()
+ def get_one(self, id):
+ return self.data[int(id)]
+
+ @expose('json')
+ def get_all(self):
+ return dict(items=self.data)
+
+ class RootController(object):
+ foos = FoosController()
+
+ # create the app
+ app = TestApp(make_app(RootController()))
+
+ # test get_all
+ r = app.get('/foos')
+ assert r.status_int == 200
+ assert r.body == b_(dumps(dict(items=FoosController.data)))
+
+ # test nested get_all
+ r = app.get('/foos/1/bars')
+ assert r.status_int == 200
+ assert r.body == b_(dumps(dict(items=BarsController.data[1])))
+
+ r = app.get('/foos/bars', expect_errors=True)
+ assert r.status_int == 404
+
def test_custom_with_trailing_slash(self):
class CustomController(RestController):