perspective.handlers.aiohttp

 1#  ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
 2#  ┃ ██████ ██████ ██████       █      █      █      █      █ █▄  ▀███ █       ┃
 3#  ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█  ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄  ▀█ █ ▀▀▀▀▀ ┃
 4#  ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄   █ ▄▄▄▄▄ ┃
 5#  ┃ █      ██████ █  ▀█▄       █ ██████      █      ███▌▐███ ███████▄ █       ┃
 6#  ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
 7#  ┃ Copyright (c) 2017, the Perspective Authors.                              ┃
 8#  ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
 9#  ┃ This file is part of the Perspective library, distributed under the terms ┃
10#  ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11#  ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13from aiohttp import web, WSMsgType
14import perspective
15import asyncio
16
17
18class PerspectiveAIOHTTPHandler(object):
19    """`PerspectiveAIOHTTPHandler` is a drop-in implementation of Perspective.
20
21    Use it inside AIOHTTP routing to create a server-side Perspective that is
22    ready to receive websocket messages from the front-end `perspective-viewer`.
23
24    The Perspective client and server will automatically keep the Websocket
25    alive without timing out.
26
27    # Examples
28
29    >>> server = Server()
30    >>> async def websocket_handler(request):
31    ...    handler = PerspectiveAIOHTTPHandler(perspective_server=server, request=request)
32    ...    await handler.run()
33
34    >>> app = web.Application()
35    >>> app.router.add_get("/websocket", websocket_handler)
36    """
37
38    def __init__(self, **kwargs):
39        self.server = kwargs.pop("perspective_server", perspective.GLOBAL_SERVER)
40        self._request = kwargs.pop("request")
41        self._executor = kwargs.pop("executor", None)
42        self._loop = kwargs.pop("loop", asyncio.get_event_loop())
43        super().__init__(**kwargs)
44
45    async def run(self) -> web.WebSocketResponse:
46        def inner(msg):
47            self._loop.create_task(self._ws.send_bytes(msg))
48
49        self.session = self.server.new_session(inner)
50        try:
51            self._ws = web.WebSocketResponse()
52            await self._ws.prepare(self._request)
53            async for msg in self._ws:
54                if msg.type == WSMsgType.BINARY:
55                    if self._executor is not None:
56                        self._executor.submit(self.session.handle_request, msg.data)
57                    else:
58                        self.session.handle_request(msg.data)
59        finally:
60            self.session.close()
61        return self._ws
class PerspectiveAIOHTTPHandler:
19class PerspectiveAIOHTTPHandler(object):
20    """`PerspectiveAIOHTTPHandler` is a drop-in implementation of Perspective.
21
22    Use it inside AIOHTTP routing to create a server-side Perspective that is
23    ready to receive websocket messages from the front-end `perspective-viewer`.
24
25    The Perspective client and server will automatically keep the Websocket
26    alive without timing out.
27
28    # Examples
29
30    >>> server = Server()
31    >>> async def websocket_handler(request):
32    ...    handler = PerspectiveAIOHTTPHandler(perspective_server=server, request=request)
33    ...    await handler.run()
34
35    >>> app = web.Application()
36    >>> app.router.add_get("/websocket", websocket_handler)
37    """
38
39    def __init__(self, **kwargs):
40        self.server = kwargs.pop("perspective_server", perspective.GLOBAL_SERVER)
41        self._request = kwargs.pop("request")
42        self._executor = kwargs.pop("executor", None)
43        self._loop = kwargs.pop("loop", asyncio.get_event_loop())
44        super().__init__(**kwargs)
45
46    async def run(self) -> web.WebSocketResponse:
47        def inner(msg):
48            self._loop.create_task(self._ws.send_bytes(msg))
49
50        self.session = self.server.new_session(inner)
51        try:
52            self._ws = web.WebSocketResponse()
53            await self._ws.prepare(self._request)
54            async for msg in self._ws:
55                if msg.type == WSMsgType.BINARY:
56                    if self._executor is not None:
57                        self._executor.submit(self.session.handle_request, msg.data)
58                    else:
59                        self.session.handle_request(msg.data)
60        finally:
61            self.session.close()
62        return self._ws

PerspectiveAIOHTTPHandler is a drop-in implementation of Perspective.

Use it inside AIOHTTP routing to create a server-side Perspective that is ready to receive websocket messages from the front-end perspective-viewer.

The Perspective client and server will automatically keep the Websocket alive without timing out.

Examples

>>> server = Server()
>>> async def websocket_handler(request):
...    handler = PerspectiveAIOHTTPHandler(perspective_server=server, request=request)
...    await handler.run()
>>> app = web.Application()
>>> app.router.add_get("/websocket", websocket_handler)
PerspectiveAIOHTTPHandler(**kwargs)
39    def __init__(self, **kwargs):
40        self.server = kwargs.pop("perspective_server", perspective.GLOBAL_SERVER)
41        self._request = kwargs.pop("request")
42        self._executor = kwargs.pop("executor", None)
43        self._loop = kwargs.pop("loop", asyncio.get_event_loop())
44        super().__init__(**kwargs)
server
async def run(self) -> aiohttp.web_ws.WebSocketResponse:
46    async def run(self) -> web.WebSocketResponse:
47        def inner(msg):
48            self._loop.create_task(self._ws.send_bytes(msg))
49
50        self.session = self.server.new_session(inner)
51        try:
52            self._ws = web.WebSocketResponse()
53            await self._ws.prepare(self._request)
54            async for msg in self._ws:
55                if msg.type == WSMsgType.BINARY:
56                    if self._executor is not None:
57                        self._executor.submit(self.session.handle_request, msg.data)
58                    else:
59                        self.session.handle_request(msg.data)
60        finally:
61            self.session.close()
62        return self._ws