Пример #1
0
class FastapiProvider(BaseProvider, protocol=constants.Protocol.HTTP):
    def __init__(
            self,
            cafile: str,
            app_name: str = '',
    ):
        super().__init__(cafile)
        self.app = FastAPI()
        self.policy_map: Dict[str, RegistrationRule] = {}

    def add_provided_service(self, rule: RegistrationRule, ) -> None:
        self.policy_map[rule.service_uri] = rule

        if rule.protocol == constants.Protocol.HTTP:
            self.app.add_api_route(
                    path=f'/{rule.service_uri.lstrip("/")}',
                    endpoint=rule.func,
                    methods=[rule.method],
            )
        elif rule.protocol == constants.Protocol.WS:
            self.app.add_api_websocket_route(
                    path=f'/{rule.service_uri}',
                    endpoint=rule.func,
            )

    def run_forever(
            self,
            address: str,
            port: int,
            keyfile: str,
            certfile: str,
    ):
        # TODO: Should http requests be redirected to https requests automatically in secure mode?
        # self.app.add_middleware(HTTPSRedirectMiddleware)
        self.app.add_middleware(ArrowheadAccessPolicyMiddleware, policy_map=self.policy_map)

        uvicorn.run(
                self.app,
                host=address,
                port=port,
                ssl_keyfile=keyfile,
                ssl_certfile=certfile,
                ssl_ca_certs=self.cafile,
        )

    def add_startup_routine(self, func: Callable):
        self.app.add_event_handler('startup', func)

    def add_shutdown_routine(self, func: Callable):
        self.app.add_event_handler('shutdown', func)
Пример #2
0

@app.get("/settings/", response_model=UpdateSettings)
async def get_settings():
    return UpdateSettings(settings=settings.serialize())


app.include_router(routers.frontend.router, tags=["Frontend"])
app.include_router(routers.sources.router, tags=["Sources"])
app.include_router(routers.nodes.router, tags=["Nodes"])

if not settings.DISABLE_PROFILE_REPORTS:
    app.include_router(routers.profile_reports.router, tags=["Profile Reports"])

if settings.ENABLE_WEBSOCKET_CONNECTIONS:
    app.add_api_websocket_route(websocket_path, websocket_endpoint)


def run():
    if not settings.DISABLE_OPEN_BROWSER:
        launch_browser_opener(f"http://{settings.HOST}:{settings.PORT}")

    dtale_app.run()

    uvicorn.run(
        app, host=socket.gethostbyname(settings.HOST), port=settings.PORT, debug=True,
    )


if __name__ == "__main__":
    run()
Пример #3
0
class Driver(ReverseDriver):
    """FastAPI 驱动框架。"""
    def __init__(self, env: Env, config: NoneBotConfig):
        super(Driver, self).__init__(env, config)

        self.fastapi_config: Config = Config(**config.dict())

        self._server_app = FastAPI(
            openapi_url=self.fastapi_config.fastapi_openapi_url,
            docs_url=self.fastapi_config.fastapi_docs_url,
            redoc_url=self.fastapi_config.fastapi_redoc_url,
        )

    @property
    @overrides(ReverseDriver)
    def type(self) -> str:
        """驱动名称: `fastapi`"""
        return "fastapi"

    @property
    @overrides(ReverseDriver)
    def server_app(self) -> FastAPI:
        """`FastAPI APP` 对象"""
        return self._server_app

    @property
    @overrides(ReverseDriver)
    def asgi(self) -> FastAPI:
        """`FastAPI APP` 对象"""
        return self._server_app

    @property
    @overrides(ReverseDriver)
    def logger(self) -> logging.Logger:
        """fastapi 使用的 logger"""
        return logging.getLogger("fastapi")

    @overrides(ReverseDriver)
    def setup_http_server(self, setup: HTTPServerSetup):
        async def _handle(request: Request) -> Response:
            return await self._handle_http(request, setup)

        self._server_app.add_api_route(
            setup.path.path,
            _handle,
            name=setup.name,
            methods=[setup.method],
            include_in_schema=self.fastapi_config.
            fastapi_include_adapter_schema,
        )

    @overrides(ReverseDriver)
    def setup_websocket_server(self, setup: WebSocketServerSetup) -> None:
        async def _handle(websocket: WebSocket) -> None:
            await self._handle_ws(websocket, setup)

        self._server_app.add_api_websocket_route(
            setup.path.path,
            _handle,
            name=setup.name,
        )

    @overrides(ReverseDriver)
    def on_startup(self, func: Callable) -> Callable:
        """参考文档: `Events <https://fastapi.tiangolo.com/advanced/events/#startup-event>`_"""
        return self.server_app.on_event("startup")(func)

    @overrides(ReverseDriver)
    def on_shutdown(self, func: Callable) -> Callable:
        """参考文档: `Events <https://fastapi.tiangolo.com/advanced/events/#shutdown-event>`_"""
        return self.server_app.on_event("shutdown")(func)

    @overrides(ReverseDriver)
    def run(
        self,
        host: Optional[str] = None,
        port: Optional[int] = None,
        *,
        app: Optional[str] = None,
        **kwargs,
    ):
        """使用 `uvicorn` 启动 FastAPI"""
        super().run(host, port, app, **kwargs)
        LOGGING_CONFIG = {
            "version": 1,
            "disable_existing_loggers": False,
            "handlers": {
                "default": {
                    "class": "nonebot.log.LoguruHandler",
                },
            },
            "loggers": {
                "uvicorn.error": {
                    "handlers": ["default"],
                    "level": "INFO"
                },
                "uvicorn.access": {
                    "handlers": ["default"],
                    "level": "INFO",
                },
            },
        }
        uvicorn.run(
            app or self.server_app,  # type: ignore
            host=host or str(self.config.host),
            port=port or self.config.port,
            reload=self.fastapi_config.fastapi_reload,
            reload_dirs=self.fastapi_config.fastapi_reload_dirs,
            reload_delay=self.fastapi_config.fastapi_reload_delay,
            reload_includes=self.fastapi_config.fastapi_reload_includes,
            reload_excludes=self.fastapi_config.fastapi_reload_excludes,
            log_config=LOGGING_CONFIG,
            **kwargs,
        )

    async def _handle_http(
        self,
        request: Request,
        setup: HTTPServerSetup,
    ) -> Response:
        json: Any = None
        try:
            json = await request.json()
        except Exception:
            pass

        data: Optional[dict] = None
        files: Optional[List[Tuple[str, FileTypes]]] = None
        try:
            form = await request.form()
            data = {}
            files = []
            for key, value in form.multi_items():
                if isinstance(value, UploadFile):
                    files.append((key, (value.filename, value.file,
                                        value.content_type)))
                else:
                    data[key] = value
        except Exception:
            pass
        http_request = BaseRequest(
            request.method,
            str(request.url),
            headers=request.headers.items(),
            cookies=request.cookies,
            content=await request.body(),
            data=data,
            json=json,
            files=files,
            version=request.scope["http_version"],
        )

        response = await setup.handle_func(http_request)
        return Response(response.content, response.status_code,
                        dict(response.headers))

    async def _handle_ws(self, websocket: WebSocket,
                         setup: WebSocketServerSetup):
        request = BaseRequest(
            "GET",
            str(websocket.url),
            headers=websocket.headers.items(),
            cookies=websocket.cookies,
            version=websocket.scope.get("http_version", "1.1"),
        )
        ws = FastAPIWebSocket(
            request=request,
            websocket=websocket,
        )

        await setup.handle_func(ws)