2020-10-16 01:10:46 +08:00
|
|
|
|
"""
|
|
|
|
|
FastAPI 驱动适配
|
|
|
|
|
================
|
|
|
|
|
|
2021-07-31 12:24:11 +08:00
|
|
|
|
本驱动同时支持服务端以及客户端连接
|
|
|
|
|
|
2020-10-16 01:10:46 +08:00
|
|
|
|
后端使用方法请参考: `FastAPI 文档`_
|
|
|
|
|
|
|
|
|
|
.. _FastAPI 文档:
|
|
|
|
|
https://fastapi.tiangolo.com/
|
|
|
|
|
"""
|
2020-07-04 22:51:10 +08:00
|
|
|
|
|
|
|
|
|
import logging
|
2021-12-06 22:19:05 +08:00
|
|
|
|
from functools import partial
|
2021-06-10 21:52:20 +08:00
|
|
|
|
from dataclasses import dataclass
|
2021-12-06 22:19:05 +08:00
|
|
|
|
from typing import Any, List, Union, Callable, Optional, Awaitable
|
2020-07-04 22:51:10 +08:00
|
|
|
|
|
2021-07-23 00:51:19 +08:00
|
|
|
|
import httpx
|
2020-07-04 22:51:10 +08:00
|
|
|
|
import uvicorn
|
2021-01-12 18:02:05 +08:00
|
|
|
|
from pydantic import BaseSettings
|
2020-08-25 18:02:18 +08:00
|
|
|
|
from fastapi.responses import Response
|
2021-12-18 23:19:37 +08:00
|
|
|
|
from fastapi import FastAPI, Request, status
|
|
|
|
|
from starlette.websockets import WebSocket, WebSocketState
|
2021-07-23 00:51:19 +08:00
|
|
|
|
from websockets.legacy.client import Connect, WebSocketClientProtocol
|
2020-07-04 22:51:10 +08:00
|
|
|
|
|
2021-09-25 19:14:16 +08:00
|
|
|
|
from nonebot.config import Env
|
2020-12-06 02:30:19 +08:00
|
|
|
|
from nonebot.typing import overrides
|
2021-09-25 19:14:16 +08:00
|
|
|
|
from nonebot.utils import escape_tag
|
|
|
|
|
from nonebot.config import Config as NoneBotConfig
|
2021-12-18 23:19:37 +08:00
|
|
|
|
from nonebot.drivers import Request as GenericRequest
|
2021-09-25 19:14:16 +08:00
|
|
|
|
from nonebot.drivers import WebSocket as BaseWebSocket
|
2021-12-18 23:19:37 +08:00
|
|
|
|
from nonebot.drivers import Response as GenericResponse
|
2021-11-22 23:21:26 +08:00
|
|
|
|
from nonebot.drivers import (
|
2021-12-18 23:19:37 +08:00
|
|
|
|
HTTPVersion,
|
2021-11-22 23:21:26 +08:00
|
|
|
|
ForwardDriver,
|
|
|
|
|
ReverseDriver,
|
2021-12-06 22:19:05 +08:00
|
|
|
|
HTTPServerSetup,
|
|
|
|
|
WebSocketServerSetup,
|
2021-11-22 23:21:26 +08:00
|
|
|
|
)
|
|
|
|
|
|
2020-08-20 16:34:07 +08:00
|
|
|
|
|
2021-01-12 18:02:05 +08:00
|
|
|
|
class Config(BaseSettings):
|
2021-02-05 13:31:33 +08:00
|
|
|
|
"""
|
|
|
|
|
FastAPI 驱动框架设置,详情参考 FastAPI 文档
|
|
|
|
|
"""
|
2021-11-22 23:21:26 +08:00
|
|
|
|
|
2021-01-12 18:02:05 +08:00
|
|
|
|
fastapi_openapi_url: Optional[str] = None
|
2021-02-05 13:31:33 +08:00
|
|
|
|
"""
|
|
|
|
|
:类型:
|
|
|
|
|
|
|
|
|
|
``Optional[str]``
|
|
|
|
|
|
|
|
|
|
:说明:
|
|
|
|
|
|
2021-03-06 11:56:58 +08:00
|
|
|
|
``openapi.json`` 地址,默认为 ``None`` 即关闭
|
2021-02-05 13:31:33 +08:00
|
|
|
|
"""
|
2021-01-12 18:02:05 +08:00
|
|
|
|
fastapi_docs_url: Optional[str] = None
|
2021-02-05 13:31:33 +08:00
|
|
|
|
"""
|
|
|
|
|
:类型:
|
|
|
|
|
|
|
|
|
|
``Optional[str]``
|
|
|
|
|
|
|
|
|
|
:说明:
|
|
|
|
|
|
2021-03-06 11:56:58 +08:00
|
|
|
|
``swagger`` 地址,默认为 ``None`` 即关闭
|
2021-02-05 13:31:33 +08:00
|
|
|
|
"""
|
2021-01-12 18:02:05 +08:00
|
|
|
|
fastapi_redoc_url: Optional[str] = None
|
2021-02-05 13:31:33 +08:00
|
|
|
|
"""
|
|
|
|
|
:类型:
|
|
|
|
|
|
|
|
|
|
``Optional[str]``
|
|
|
|
|
|
|
|
|
|
:说明:
|
|
|
|
|
|
2021-03-06 11:56:58 +08:00
|
|
|
|
``redoc`` 地址,默认为 ``None`` 即关闭
|
|
|
|
|
"""
|
2021-10-02 15:35:15 +08:00
|
|
|
|
fastapi_reload: Optional[bool] = None
|
2021-09-28 21:20:29 +08:00
|
|
|
|
"""
|
|
|
|
|
:类型:
|
|
|
|
|
|
2021-10-02 15:35:15 +08:00
|
|
|
|
``Optional[bool]``
|
2021-09-28 21:20:29 +08:00
|
|
|
|
|
|
|
|
|
:说明:
|
|
|
|
|
|
2021-10-02 15:35:15 +08:00
|
|
|
|
开启/关闭冷重载,默认会在配置了 app 的 debug 模式启用
|
2021-09-28 21:20:29 +08:00
|
|
|
|
"""
|
2021-10-02 15:35:15 +08:00
|
|
|
|
fastapi_reload_dirs: Optional[List[str]] = None
|
2021-03-06 11:56:58 +08:00
|
|
|
|
"""
|
|
|
|
|
:类型:
|
|
|
|
|
|
2021-10-02 15:35:15 +08:00
|
|
|
|
``Optional[List[str]]``
|
2021-03-06 11:56:58 +08:00
|
|
|
|
|
|
|
|
|
:说明:
|
|
|
|
|
|
2021-09-28 21:20:29 +08:00
|
|
|
|
重载监控文件夹列表,默认为 uvicorn 默认值
|
|
|
|
|
"""
|
|
|
|
|
fastapi_reload_delay: Optional[float] = None
|
|
|
|
|
"""
|
|
|
|
|
:类型:
|
|
|
|
|
|
|
|
|
|
``Optional[float]``
|
|
|
|
|
|
|
|
|
|
:说明:
|
|
|
|
|
|
|
|
|
|
重载延迟,默认为 uvicorn 默认值
|
2021-02-05 13:31:33 +08:00
|
|
|
|
"""
|
2021-10-02 15:35:15 +08:00
|
|
|
|
fastapi_reload_includes: Optional[List[str]] = None
|
2021-09-30 01:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
:类型:
|
|
|
|
|
|
2021-10-02 15:35:15 +08:00
|
|
|
|
``Optional[List[str]]``
|
2021-09-30 01:22:12 +08:00
|
|
|
|
|
|
|
|
|
:说明:
|
|
|
|
|
|
|
|
|
|
要监听的文件列表,支持 glob pattern,默认为 uvicorn 默认值
|
|
|
|
|
"""
|
2021-10-02 15:35:15 +08:00
|
|
|
|
fastapi_reload_excludes: Optional[List[str]] = None
|
2021-09-30 01:22:12 +08:00
|
|
|
|
"""
|
|
|
|
|
:类型:
|
|
|
|
|
|
2021-10-02 15:35:15 +08:00
|
|
|
|
``Optional[List[str]]``
|
2021-09-30 01:22:12 +08:00
|
|
|
|
|
|
|
|
|
:说明:
|
|
|
|
|
|
|
|
|
|
不要监听的文件列表,支持 glob pattern,默认为 uvicorn 默认值
|
|
|
|
|
"""
|
2021-01-12 18:02:05 +08:00
|
|
|
|
|
|
|
|
|
class Config:
|
|
|
|
|
extra = "ignore"
|
|
|
|
|
|
|
|
|
|
|
2021-11-27 12:16:31 +08:00
|
|
|
|
class Driver(ReverseDriver):
|
2021-12-06 22:19:05 +08:00
|
|
|
|
"""FastAPI 驱动框架。包含反向 Server 功能。"""
|
2020-07-04 22:51:10 +08:00
|
|
|
|
|
2021-01-12 18:02:05 +08:00
|
|
|
|
def __init__(self, env: Env, config: NoneBotConfig):
|
2021-11-27 12:16:31 +08:00
|
|
|
|
super(Driver, self).__init__(env, config)
|
2020-08-07 17:51:57 +08:00
|
|
|
|
|
2021-07-23 00:51:19 +08:00
|
|
|
|
self.fastapi_config: Config = Config(**config.dict())
|
2021-01-12 18:02:05 +08:00
|
|
|
|
|
2020-07-04 22:51:10 +08:00
|
|
|
|
self._server_app = FastAPI(
|
|
|
|
|
debug=config.debug,
|
2021-01-12 18:02:05 +08:00
|
|
|
|
openapi_url=self.fastapi_config.fastapi_openapi_url,
|
|
|
|
|
docs_url=self.fastapi_config.fastapi_docs_url,
|
|
|
|
|
redoc_url=self.fastapi_config.fastapi_redoc_url,
|
2020-07-04 22:51:10 +08:00
|
|
|
|
)
|
|
|
|
|
|
2020-08-13 15:56:09 +08:00
|
|
|
|
@property
|
2021-05-21 17:06:20 +08:00
|
|
|
|
@overrides(ReverseDriver)
|
2020-08-13 15:56:09 +08:00
|
|
|
|
def type(self) -> str:
|
2020-10-16 01:10:46 +08:00
|
|
|
|
"""驱动名称: ``fastapi``"""
|
2020-08-13 15:56:09 +08:00
|
|
|
|
return "fastapi"
|
|
|
|
|
|
2020-07-04 22:51:10 +08:00
|
|
|
|
@property
|
2021-05-21 17:06:20 +08:00
|
|
|
|
@overrides(ReverseDriver)
|
2020-08-11 10:44:05 +08:00
|
|
|
|
def server_app(self) -> FastAPI:
|
2020-10-16 01:10:46 +08:00
|
|
|
|
"""``FastAPI APP`` 对象"""
|
2020-07-04 22:51:10 +08:00
|
|
|
|
return self._server_app
|
|
|
|
|
|
|
|
|
|
@property
|
2021-05-21 17:06:20 +08:00
|
|
|
|
@overrides(ReverseDriver)
|
2021-06-15 01:23:12 +08:00
|
|
|
|
def asgi(self) -> FastAPI:
|
2020-10-16 01:10:46 +08:00
|
|
|
|
"""``FastAPI APP`` 对象"""
|
2020-07-04 22:51:10 +08:00
|
|
|
|
return self._server_app
|
|
|
|
|
|
|
|
|
|
@property
|
2021-05-21 17:06:20 +08:00
|
|
|
|
@overrides(ReverseDriver)
|
2020-08-01 22:03:40 +08:00
|
|
|
|
def logger(self) -> logging.Logger:
|
2020-10-16 01:10:46 +08:00
|
|
|
|
"""fastapi 使用的 logger"""
|
2020-07-04 22:51:10 +08:00
|
|
|
|
return logging.getLogger("fastapi")
|
|
|
|
|
|
2021-12-06 22:19:05 +08:00
|
|
|
|
@overrides(ReverseDriver)
|
|
|
|
|
def setup_http_server(self, setup: HTTPServerSetup):
|
2021-12-18 23:19:37 +08:00
|
|
|
|
async def _handle(request: Request) -> Response:
|
|
|
|
|
return await self._handle_http(request, setup)
|
2021-12-06 22:19:05 +08:00
|
|
|
|
|
|
|
|
|
self._server_app.add_api_route(
|
2021-12-18 23:19:37 +08:00
|
|
|
|
setup.path.path,
|
|
|
|
|
_handle,
|
2021-12-06 22:19:05 +08:00
|
|
|
|
methods=[setup.method],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
@overrides(ReverseDriver)
|
|
|
|
|
def setup_websocket_server(self, setup: WebSocketServerSetup) -> None:
|
2021-12-18 23:19:37 +08:00
|
|
|
|
async def _handle(websocket: WebSocket):
|
|
|
|
|
await self._handle_ws(websocket, setup)
|
2021-12-06 22:19:05 +08:00
|
|
|
|
|
|
|
|
|
self._server_app.add_api_websocket_route(
|
2021-12-18 23:19:37 +08:00
|
|
|
|
setup.path.path,
|
|
|
|
|
_handle,
|
2021-12-06 22:19:05 +08:00
|
|
|
|
)
|
|
|
|
|
|
2021-05-21 17:06:20 +08:00
|
|
|
|
@overrides(ReverseDriver)
|
2020-08-11 10:44:05 +08:00
|
|
|
|
def on_startup(self, func: Callable) -> Callable:
|
2020-10-16 01:10:46 +08:00
|
|
|
|
"""参考文档: `Events <https://fastapi.tiangolo.com/advanced/events/#startup-event>`_"""
|
2020-08-11 10:44:05 +08:00
|
|
|
|
return self.server_app.on_event("startup")(func)
|
|
|
|
|
|
2021-05-21 17:06:20 +08:00
|
|
|
|
@overrides(ReverseDriver)
|
2020-08-11 10:44:05 +08:00
|
|
|
|
def on_shutdown(self, func: Callable) -> Callable:
|
2020-10-16 01:10:46 +08:00
|
|
|
|
"""参考文档: `Events <https://fastapi.tiangolo.com/advanced/events/#startup-event>`_"""
|
2020-08-11 10:44:05 +08:00
|
|
|
|
return self.server_app.on_event("shutdown")(func)
|
|
|
|
|
|
2021-05-21 17:06:20 +08:00
|
|
|
|
@overrides(ReverseDriver)
|
2021-11-22 23:21:26 +08:00
|
|
|
|
def run(
|
|
|
|
|
self,
|
|
|
|
|
host: Optional[str] = None,
|
|
|
|
|
port: Optional[int] = None,
|
|
|
|
|
*,
|
|
|
|
|
app: Optional[str] = None,
|
|
|
|
|
**kwargs,
|
|
|
|
|
):
|
2020-10-16 01:10:46 +08:00
|
|
|
|
"""使用 ``uvicorn`` 启动 FastAPI"""
|
2020-12-02 13:17:27 +08:00
|
|
|
|
super().run(host, port, app, **kwargs)
|
2020-07-04 22:51:10 +08:00
|
|
|
|
LOGGING_CONFIG = {
|
|
|
|
|
"version": 1,
|
|
|
|
|
"disable_existing_loggers": False,
|
|
|
|
|
"handlers": {
|
|
|
|
|
"default": {
|
2020-08-27 13:27:42 +08:00
|
|
|
|
"class": "nonebot.log.LoguruHandler",
|
2020-07-04 22:51:10 +08:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"loggers": {
|
2021-11-22 23:21:26 +08:00
|
|
|
|
"uvicorn.error": {"handlers": ["default"], "level": "INFO"},
|
2020-07-04 22:51:10 +08:00
|
|
|
|
"uvicorn.access": {
|
|
|
|
|
"handlers": ["default"],
|
|
|
|
|
"level": "INFO",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
2021-07-23 00:51:19 +08:00
|
|
|
|
uvicorn.run(
|
|
|
|
|
app or self.server_app, # type: ignore
|
|
|
|
|
host=host or str(self.config.host),
|
|
|
|
|
port=port or self.config.port,
|
2021-10-02 15:35:15 +08:00
|
|
|
|
reload=self.fastapi_config.fastapi_reload
|
2021-11-22 23:21:26 +08:00
|
|
|
|
if self.fastapi_config.fastapi_reload is not None
|
|
|
|
|
else (bool(app) and self.config.debug),
|
2021-10-02 15:35:15 +08:00
|
|
|
|
reload_dirs=self.fastapi_config.fastapi_reload_dirs,
|
2021-09-28 21:20:29 +08:00
|
|
|
|
reload_delay=self.fastapi_config.fastapi_reload_delay,
|
2021-10-02 15:35:15 +08:00
|
|
|
|
reload_includes=self.fastapi_config.fastapi_reload_includes,
|
|
|
|
|
reload_excludes=self.fastapi_config.fastapi_reload_excludes,
|
2021-07-23 00:51:19 +08:00
|
|
|
|
debug=self.config.debug,
|
|
|
|
|
log_config=LOGGING_CONFIG,
|
2021-11-22 23:21:26 +08:00
|
|
|
|
**kwargs,
|
|
|
|
|
)
|
2021-07-23 00:51:19 +08:00
|
|
|
|
|
2021-12-06 22:19:05 +08:00
|
|
|
|
async def _handle_http(
|
|
|
|
|
self,
|
|
|
|
|
request: Request,
|
2021-12-18 23:19:37 +08:00
|
|
|
|
setup: HTTPServerSetup,
|
2021-12-06 22:19:05 +08:00
|
|
|
|
):
|
2021-12-18 23:19:37 +08:00
|
|
|
|
http_request = GenericRequest(
|
2021-11-22 23:21:26 +08:00
|
|
|
|
request.method,
|
2021-12-18 23:19:37 +08:00
|
|
|
|
str(request.url),
|
|
|
|
|
headers=request.headers.items(),
|
|
|
|
|
cookies=request.cookies,
|
|
|
|
|
content=await request.body(),
|
|
|
|
|
version=request.scope["http_version"],
|
2021-11-22 23:21:26 +08:00
|
|
|
|
)
|
2020-08-25 18:02:18 +08:00
|
|
|
|
|
2021-12-18 23:19:37 +08:00
|
|
|
|
response = await setup.handle_func(http_request)
|
|
|
|
|
return Response(response.content, response.status_code, dict(response.headers))
|
2020-08-10 13:06:02 +08:00
|
|
|
|
|
2021-12-18 23:19:37 +08:00
|
|
|
|
async def _handle_ws(self, websocket: WebSocket, setup: WebSocketServerSetup):
|
|
|
|
|
request = GenericRequest(
|
|
|
|
|
"GET",
|
|
|
|
|
str(websocket.url),
|
|
|
|
|
headers=websocket.headers.items(),
|
|
|
|
|
cookies=websocket.cookies,
|
|
|
|
|
version=websocket.scope["http_version"],
|
|
|
|
|
)
|
|
|
|
|
ws = FastAPIWebSocket(
|
|
|
|
|
request=request,
|
|
|
|
|
websocket=websocket,
|
2021-11-22 23:21:26 +08:00
|
|
|
|
)
|
2020-08-25 18:02:18 +08:00
|
|
|
|
|
2021-12-18 23:19:37 +08:00
|
|
|
|
await setup.handle_func(ws)
|
2020-07-15 20:39:59 +08:00
|
|
|
|
|
2021-11-27 12:16:31 +08:00
|
|
|
|
|
|
|
|
|
class FullDriver(ForwardDriver, Driver):
|
|
|
|
|
"""
|
|
|
|
|
完整的 FastAPI 驱动框架,包含正向 Client 支持和反向 Server 支持。
|
|
|
|
|
|
|
|
|
|
:使用方法:
|
|
|
|
|
|
|
|
|
|
.. code-block:: dotenv
|
|
|
|
|
|
|
|
|
|
DRIVER=nonebot.drivers.fastapi:FullDriver
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
@property
|
2021-12-18 23:19:37 +08:00
|
|
|
|
@overrides(Driver)
|
2021-11-27 12:16:31 +08:00
|
|
|
|
def type(self) -> str:
|
|
|
|
|
"""驱动名称: ``fastapi_full``"""
|
|
|
|
|
return "fastapi_full"
|
|
|
|
|
|
|
|
|
|
@overrides(ForwardDriver)
|
2021-12-18 23:19:37 +08:00
|
|
|
|
async def request(self, setup: "GenericRequest") -> Any:
|
2021-12-06 22:19:05 +08:00
|
|
|
|
async with httpx.AsyncClient(
|
2021-12-18 23:19:37 +08:00
|
|
|
|
http2=setup.version == HTTPVersion.H2, follow_redirects=True
|
2021-12-06 22:19:05 +08:00
|
|
|
|
) as client:
|
|
|
|
|
response = await client.request(
|
|
|
|
|
setup.method,
|
2021-12-18 23:19:37 +08:00
|
|
|
|
str(setup.url),
|
|
|
|
|
content=setup.content,
|
|
|
|
|
headers=tuple(setup.headers.items()),
|
2021-12-06 22:19:05 +08:00
|
|
|
|
timeout=30.0,
|
2021-11-22 23:21:26 +08:00
|
|
|
|
)
|
2021-12-18 23:19:37 +08:00
|
|
|
|
return GenericResponse(
|
|
|
|
|
response.status_code,
|
|
|
|
|
headers=response.headers,
|
|
|
|
|
content=response.content,
|
|
|
|
|
request=setup,
|
2021-12-02 20:52:39 +08:00
|
|
|
|
)
|
2021-07-31 12:24:11 +08:00
|
|
|
|
|
2021-12-06 22:19:05 +08:00
|
|
|
|
@overrides(ForwardDriver)
|
2021-12-18 23:19:37 +08:00
|
|
|
|
async def websocket(self, setup: "GenericRequest") -> Any:
|
|
|
|
|
ws = await Connect(str(setup.url), extra_headers=setup.headers.items())
|
|
|
|
|
return WebSocketsWS(request=setup, websocket=ws)
|
2021-07-23 00:51:19 +08:00
|
|
|
|
|
2020-07-15 20:39:59 +08:00
|
|
|
|
|
2021-12-18 23:19:37 +08:00
|
|
|
|
class WebSocketsWS(BaseWebSocket):
|
|
|
|
|
@overrides(BaseWebSocket)
|
|
|
|
|
def __init__(self, *, request: GenericRequest, websocket: WebSocketClientProtocol):
|
|
|
|
|
super().__init__(request=request)
|
|
|
|
|
self.websocket = websocket
|
2020-07-15 20:39:59 +08:00
|
|
|
|
|
|
|
|
|
@property
|
2020-08-07 17:51:57 +08:00
|
|
|
|
@overrides(BaseWebSocket)
|
2021-07-23 00:51:19 +08:00
|
|
|
|
def closed(self) -> bool:
|
2021-12-18 23:19:37 +08:00
|
|
|
|
# if isinstance(self.websocket, WebSocket):
|
|
|
|
|
# return (
|
|
|
|
|
# self.websocket.client_state == WebSocketState.DISCONNECTED
|
|
|
|
|
# or self.websocket.application_state == WebSocketState.DISCONNECTED
|
|
|
|
|
# )
|
|
|
|
|
return self.websocket.closed
|
|
|
|
|
|
|
|
|
|
@overrides(BaseWebSocket)
|
|
|
|
|
async def accept(self):
|
|
|
|
|
# if isinstance(self.websocket, WebSocket):
|
|
|
|
|
# await self.websocket.accept()
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
|
|
@overrides(BaseWebSocket)
|
|
|
|
|
async def close(self, code: int = 1000):
|
|
|
|
|
await self.websocket.close(code)
|
|
|
|
|
|
|
|
|
|
@overrides(BaseWebSocket)
|
|
|
|
|
async def receive(self) -> str:
|
|
|
|
|
# if isinstance(self.websocket, WebSocket):
|
|
|
|
|
# return await self.websocket.receive_text()
|
|
|
|
|
msg = await self.websocket.recv()
|
|
|
|
|
if isinstance(msg, bytes):
|
|
|
|
|
raise TypeError("WebSocket received unexpected frame type: bytes")
|
|
|
|
|
return msg
|
|
|
|
|
|
|
|
|
|
@overrides(BaseWebSocket)
|
|
|
|
|
async def receive_bytes(self) -> bytes:
|
|
|
|
|
# if isinstance(self.websocket, WebSocket):
|
|
|
|
|
# return await self.websocket.receive_bytes()
|
|
|
|
|
msg = await self.websocket.recv()
|
|
|
|
|
if isinstance(msg, str):
|
|
|
|
|
raise TypeError("WebSocket received unexpected frame type: str")
|
|
|
|
|
return msg
|
|
|
|
|
|
|
|
|
|
@overrides(BaseWebSocket)
|
|
|
|
|
async def send(self, data: str) -> None:
|
|
|
|
|
# if isinstance(self.websocket, WebSocket):
|
|
|
|
|
# await self.websocket.send({"type": "websocket.send", "text": data})
|
|
|
|
|
await self.websocket.send(data)
|
|
|
|
|
|
|
|
|
|
@overrides(BaseWebSocket)
|
|
|
|
|
async def send_bytes(self, data: bytes) -> None:
|
|
|
|
|
# if isinstance(self.websocket, WebSocket):
|
|
|
|
|
# await self.websocket.send({"type": "websocket.send", "bytes": data})
|
|
|
|
|
await self.websocket.send(data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FastAPIWebSocket(BaseWebSocket):
|
|
|
|
|
@overrides(BaseWebSocket)
|
|
|
|
|
def __init__(self, *, request: GenericRequest, websocket: WebSocket):
|
|
|
|
|
super().__init__(request=request)
|
|
|
|
|
self.websocket = websocket
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@overrides(BaseWebSocket)
|
|
|
|
|
def closed(self) -> bool:
|
|
|
|
|
return (
|
|
|
|
|
self.websocket.client_state == WebSocketState.DISCONNECTED
|
|
|
|
|
or self.websocket.application_state == WebSocketState.DISCONNECTED
|
|
|
|
|
)
|
2020-07-15 20:39:59 +08:00
|
|
|
|
|
2020-08-07 17:51:57 +08:00
|
|
|
|
@overrides(BaseWebSocket)
|
2020-07-15 20:39:59 +08:00
|
|
|
|
async def accept(self):
|
2021-12-18 23:19:37 +08:00
|
|
|
|
await self.websocket.accept()
|
2020-07-15 20:39:59 +08:00
|
|
|
|
|
2020-08-07 17:51:57 +08:00
|
|
|
|
@overrides(BaseWebSocket)
|
2020-08-01 22:03:40 +08:00
|
|
|
|
async def close(self, code: int = status.WS_1000_NORMAL_CLOSURE):
|
2021-07-23 00:51:19 +08:00
|
|
|
|
await self.websocket.close(code)
|
2020-07-15 20:39:59 +08:00
|
|
|
|
|
2020-08-07 17:51:57 +08:00
|
|
|
|
@overrides(BaseWebSocket)
|
2021-06-10 21:52:20 +08:00
|
|
|
|
async def receive(self) -> str:
|
2021-12-18 23:19:37 +08:00
|
|
|
|
return await self.websocket.receive_text()
|
2021-06-10 21:52:20 +08:00
|
|
|
|
|
|
|
|
|
@overrides(BaseWebSocket)
|
|
|
|
|
async def receive_bytes(self) -> bytes:
|
2021-12-18 23:19:37 +08:00
|
|
|
|
return await self.websocket.receive_bytes()
|
2021-06-10 21:52:20 +08:00
|
|
|
|
|
|
|
|
|
@overrides(BaseWebSocket)
|
|
|
|
|
async def send(self, data: str) -> None:
|
2021-12-18 23:19:37 +08:00
|
|
|
|
await self.websocket.send({"type": "websocket.send", "text": data})
|
2020-07-15 20:39:59 +08:00
|
|
|
|
|
2020-08-07 17:51:57 +08:00
|
|
|
|
@overrides(BaseWebSocket)
|
2021-06-10 21:52:20 +08:00
|
|
|
|
async def send_bytes(self, data: bytes) -> None:
|
2021-12-18 23:19:37 +08:00
|
|
|
|
await self.websocket.send({"type": "websocket.send", "bytes": data})
|