Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subapps #1301

Merged
merged 20 commits into from
Oct 27, 2016
Merged

Subapps #1301

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions aiohttp/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,29 @@ def http_exception(self):
def get_info(self):
"""Return a dict with additional info useful for introspection"""

@property # pragma: no branch
@abstractmethod
def apps(self):
"""Stack of nested applications.

Top level application is left-most element.

"""

@abstractmethod
def add_app(self, app):
"""Add application to the nested apps stack."""

@abstractmethod
def freeze(self):
"""Freeze the match info.

The method is called after route resolution.

After the call .add_app() is forbidden.

"""


class AbstractView(ABC):

Expand Down
9 changes: 7 additions & 2 deletions aiohttp/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from .helpers import sentinel
from .protocol import HttpVersion, RawRequestMessage
from .signals import Signal
from .web import Application, Request
from .web import Application, Request, UrlMappingMatchInfo

PY_35 = sys.version_info >= (3, 5)

Expand Down Expand Up @@ -66,6 +66,7 @@ def start_server(self, **kwargs):
self._root = URL('{}://{}:{}'.format(self.scheme,
self.host,
self.port))
yield from self.app.startup()
self.handler = self.app.make_handler(**kwargs)
self.server = yield from self._loop.create_server(self.handler,
self.host,
Expand Down Expand Up @@ -502,10 +503,14 @@ def make_mocked_request(method, path, headers=None, *,
if payload is sentinel:
payload = mock.Mock()

req = Request(app, message, payload,
req = Request(message, payload,
transport, reader, writer,
secure_proxy_ssl_header=secure_proxy_ssl_header)

match_info = UrlMappingMatchInfo({}, mock.Mock())
match_info.add_app(app)
req._match_info = match_info

return req


Expand Down
19 changes: 13 additions & 6 deletions aiohttp/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ def __init__(self, manager, app, router, *,
self._manager = manager
self._app = app
self._router = router
self._middlewares = app.middlewares
self._secure_proxy_ssl_header = secure_proxy_ssl_header

def __repr__(self):
Expand All @@ -65,15 +64,16 @@ def handle_request(self, message, payload):

app = self._app
request = web_reqrep.Request(
app, message, payload,
message, payload,
self.transport, self.reader, self.writer,
secure_proxy_ssl_header=self._secure_proxy_ssl_header)
self._meth = request.method
self._path = request.path
try:
match_info = yield from self._router.resolve(request)

assert isinstance(match_info, AbstractMatchInfo), match_info
match_info.add_app(app)
match_info.freeze()

resp = None
request._match_info = match_info
Expand All @@ -84,7 +84,7 @@ def handle_request(self, message, payload):

if resp is None:
handler = match_info.handler
for factory in reversed(self._middlewares):
for factory in match_info.middlewares:
handler = yield from factory(app, handler)
resp = yield from handler(request)

Expand Down Expand Up @@ -166,7 +166,7 @@ def __init__(self, *, logger=web_logger, loop=None,
if loop is None:
loop = asyncio.get_event_loop()
if router is None:
router = web_urldispatcher.UrlDispatcher()
router = web_urldispatcher.UrlDispatcher(self)
assert isinstance(router, AbstractRouter), router

self._debug = debug
Expand All @@ -188,6 +188,13 @@ def __init__(self, *, logger=web_logger, loop=None,
def debug(self):
return self._debug

def _reg_subapp_signals(self, subapp):
self._on_pre_signal.extend(subapp.on_pre_signal)
self._on_post_signal.extend(subapp.on_post_signal)
self._on_startup.extend(subapp.on_startup)
self._on_shutdown.extend(subapp.on_shutdown)
self._on_cleanup.extend(subapp.on_cleanup)

@property
def on_response_prepare(self):
return self._on_response_prepare
Expand Down Expand Up @@ -288,7 +295,7 @@ def __call__(self):
return self

def __repr__(self):
return "<Application>"
return "<Application 0x{:x}>".format(id(self))


def run_app(app, *, host='0.0.0.0', port=None,
Expand Down
11 changes: 6 additions & 5 deletions aiohttp/web_reqrep.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ class Request(dict, HeadersMixin):
POST_METHODS = {hdrs.METH_PATCH, hdrs.METH_POST, hdrs.METH_PUT,
hdrs.METH_TRACE, hdrs.METH_DELETE}

def __init__(self, app, message, payload, transport, reader, writer, *,
def __init__(self, message, payload, transport, reader, writer, *,
secure_proxy_ssl_header=None):
self._app = app
self._app = None
self._message = message
self._transport = transport
self._reader = reader
Expand Down Expand Up @@ -274,10 +274,10 @@ def match_info(self):
"""Result of route resolving."""
return self._match_info

@property
@reify
def app(self):
"""Application instance."""
return self._app
return self._match_info.apps[-1]

@property
def transport(self):
Expand Down Expand Up @@ -724,7 +724,8 @@ def prepare(self, request):
resp_impl = self._start_pre_check(request)
if resp_impl is not None:
return resp_impl
yield from request.app.on_response_prepare.send(request, self)
for app in request.match_info.apps:
yield from app.on_response_prepare.send(request, self)

return self._start(request)

Expand Down
Loading