diff --git a/CHANGES.rst b/CHANGES.rst index 045e268309d..66e1d47f103 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -41,7 +41,7 @@ CHANGES - Introduce `router.post_init()` for solving #1373 -- +- Allow to raise web exceptions on router resolving stage #1460 - diff --git a/aiohttp/abc.py b/aiohttp/abc.py index 31c1d307ec5..fb426f14421 100644 --- a/aiohttp/abc.py +++ b/aiohttp/abc.py @@ -11,9 +11,14 @@ class AbstractRouter(ABC): def __init__(self): self._frozen = False - @abstractmethod def post_init(self, app): - pass # pragma: no cover + """Post init stage. + + It's not an abstract method for sake of backward compatibility + but if router wans to be aware about application it should + override it. + + """ @property def frozen(self): diff --git a/aiohttp/web_reqrep.py b/aiohttp/web_reqrep.py index 4e161eeb942..c91aa898dbc 100644 --- a/aiohttp/web_reqrep.py +++ b/aiohttp/web_reqrep.py @@ -486,7 +486,10 @@ def app(self): @asyncio.coroutine def _prepare_hook(self, response): - for app in self.match_info.apps: + match_info = self._match_info + if match_info is None: + return + for app in match_info.apps: yield from app.on_response_prepare.send(self, response) diff --git a/tests/test_web_urldispatcher.py b/tests/test_web_urldispatcher.py index e29f3875e5b..2d8733c8652 100644 --- a/tests/test_web_urldispatcher.py +++ b/tests/test_web_urldispatcher.py @@ -8,7 +8,7 @@ import pytest -from aiohttp import web +from aiohttp import abc, web from aiohttp.web_urldispatcher import SystemRoute @@ -270,3 +270,21 @@ def test_system_route(): assert "" == repr(route) assert 201 == route.status assert 'test' == route.reason + + +@asyncio.coroutine +def test_412_is_returned(loop, test_client): + + class MyRouter(abc.AbstractRouter): + + @asyncio.coroutine + def resolve(self, request): + raise web.HTTPPreconditionFailed() + + app = web.Application(router=MyRouter(), loop=loop) + + client = yield from test_client(app) + + resp = yield from client.get('/') + + assert resp.status == 412