为aiohttp管理会话的websockets
项目描述
简单来说:将您的websockets与用户的会话关联起来,并在您认为合适的时候关闭这些连接。
例如,假设您正在使用 aiohttp_security,并且用户选择登录或登出。使用 aiohttp_session_ws,您可以断开与他们的会话关联的打开的websocket订阅,并强制他们重新连接并重新授权他们的websocket订阅。
基本示例
此示例中的代码片段取自本存储库的 demo 目录。
async def handle_root(request):
return web.Response(text='Hello world', content_type="text/html")
async def handle_reset(request):
session_ws_id = await get_session_ws_id(request)
response = web.Response(
text=f"Reset called on session {session_ws_id}!",
content_type="text/plain",
)
await schedule_close_all_session_ws(request, response)
await new_session_ws_id(request)
return response
async def handle_websocket(request):
async with session_ws(request) as wsr:
connected_at = datetime.now()
session_ws_id = await get_session_ws_id(request)
while True:
await wsr.send_str(
f"Websocket associated with session [{session_ws_id}] "
f"connected for {(datetime.now() - connected_at).seconds}"
)
await asyncio.sleep(1)
return wsr
def make_app():
app = web.Application(
middlewares=[
aiohttp_session.session_middleware(
aiohttp_session.SimpleCookieStorage()
),
session_ws_middleware,
]
)
app.router.add_get("/", handle_root)
app.router.add_get("/reset", handle_reset)
app.router.add_get("/ws", handle_websocket)
setup_session_websockets(app, SessionWSRegistry())
return app
使用 demo 文件夹中的代码,该文件夹包括一个简单的模板,用于在您的网页浏览器中与websocket交互。
叙事API
此软件包设计得简单易用。此轻量级文档并不试图取代阅读代码的需求,因此鼓励您亲自去阅读代码。
有几个组件,但如果(以及何时)您需要做更复杂的事情,您可以通过子类化来做到这一点。
SessionWSRegistry
这是 aiohttp_session_ws 的核心。
它的构建值得注意
SessionWSRegistry(self, *, id_factory, session_key)
id_factory 生成一个会话范围内的id,用于关联websockets。默认的id_factory返回UUID4,但您可以提供自己的可调用对象(也支持异步可调用对象)。id_factory 的函数签名是
id_factory(request: aiohttp.web.Request) -> typing.Hashable
基本上,返回可以作为字典键的值(字符串、整数等)。
session_key 是会话中映射到会话级 WebSocket 标识符的键的名称。默认情况下,它是合理的 aiohttp_session_ws_id。
辅助工具
创建 SessionWSRegistry 之后,您不需要直接与之交互,但要知道它在您的 aiohttp.web.Application 中可用(如这样访问:app['aiohttp_session_ws_registry'])。
该对象的友好全局操作符为
get_session_ws_id(request)
new_session_ws_id(request)
delete_session_ws_id(request)
ensure_session_ws_id(request)
schedule_close_all_session_ws(request, response)
这些方法可以直接从 aiohttp_session_ws 导入。
注意,schedule_close_all_session_ws 接受一个响应对象。这允许我们通过 aiohttp.web.Response.force_close 终止响应的 keep-alive 状态。这意味着一旦您的用户完成接收响应,他们未完成的 WebSocket 将关闭。
这也意味着如果您有重新连接 WebSocket 的用户,您可能需要遵循以下模式
async def handle_logout(request):
response = web.HTTPFound('/')
await schedule_close_all_session_ws(request, response)
await aiohttp_session.new_session(request)
await new_session_ws_id(request)
return response
session_ws
要跟踪 WebSocket,您将使用异步上下文管理器 session_ws。此上下文管理器升级请求,并提供其 aiothttp.web.WebSocketResponse 对应物。这样使用
async def handle_websocket(request):
async with session_ws(request) as wsr:
async for msg in wsr:
await wsr.send_str(f'Heard: {ws.data}')
return wsr
就是这样。很简单,对吧?如果您想向 aiohttp.web.WebSocketResponse 提供初始化选项(例如,支持的 WebSocket 协议),请将这些选项作为命名参数传递给 session_ws。
async def handle_websocket(request):
async with session_ws(request, protocols=('graphql-ws',)) as wsr:
async for msg in wsr:
await wsr.send_str(f'Heard: {ws.data}')
return wsr
如下面的 注意 中所述,在尝试 WebSocket 连接之前,确保您的用户有一个 session_ws id 是很重要的(提示:Safari)。
使用 session_ws_middleware 自动将键添加到您的会话中。它应该位于 aiohttp_session.session_middleware 的调用栈中
web.Application(
middlewares=[
aiohttp_session.session_middleware(
aiohttp_session.SimpleCookieStorage()
),
session_ws_middleware,
]
)
最后,要设置所有这些,您将想要使用 setup 方法(鼓励您将其导入为 setup_session_ws)。
基本用法如下
web.Application(
middlewares=[
aiohttp_session.session_middleware(
aiohttp_session.SimpleCookieStorage()
),
session_ws_middleware,
]
)
setup(app, SessionWSRegistry()) # <------
# etc...
return app
注意
虽然 session_ws 在连接时生成 aiohttp_session_ws_id(如果不存在),但某些浏览器不尊重 WebSocket 升级时的 Set-Cookie(例如 Safari)。
因此,在尝试 WebSocket 连接之前,确保用户的会话中存在 aiohttp_session_ws_id 是最好的(如果使用 aiohttp_session.SimpleCookieStorage 或 aiohttp_session.EncryptedCookieStorage)。
如果您使用更高级的存储会话引用的会话 cookie(并在服务器端存储实际值,如 aiohttp_session.RedisStorage),则 aiohttp_session_ws_id 在 cookie 中设置的时间并不重要,但仍然很重要,即用户在连接尝试之前必须有一个会话 cookie。
如果您想在会话中将 session-ws-id(通常是 aiohttp_session_ws_id)放在其他地方,或者从请求中派生它,您可以这样做。只需将 SessionWSRegistry 子类化,并修改 get_id、set_id 和 delete_id 方法。
如果您有一个Web服务器集群,您需要将SessionWSRegistry子类化,并修改register和unregister函数,以便在消息代理上监听(例如,使用aioredis及其pubsub功能)。
项目详情
aiohttp_session_ws-1.1.1.tar.gz的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | 9c697a816205e46fcabca85d32712d2ed6092aad84ef7d3b8ccd12588d6c49a5 |
|
MD5 | 92a512cbb05dd1fd4e6d3b21f99d7a33 |
|
BLAKE2b-256 | 21d4070169c88a7d5b6cd621242c7c255caa59546d0ad904f3527027d3281275 |
aiohttp_session_ws-1.1.1-py3-none-any.whl的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | f3cb6ae9dc1c0c87e6426f922123f62b9c97b02bd727a64d1db8c70d28c0f8e8 |
|
MD5 | 89469fc8228802d5622cdc5b960985df |
|
BLAKE2b-256 | a6a370857e7b59fa7fbb85e2f3e2e64aa951d192f5aab597845203376856af24 |