registrar.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. import asyncio
  4. import threading
  5. from contextlib import asynccontextmanager
  6. from fastapi import Depends, FastAPI, APIRouter
  7. from fastapi_limiter import FastAPILimiter
  8. from fastapi_pagination import add_pagination
  9. from starlette.middleware.authentication import AuthenticationMiddleware
  10. from app.router import route, call_center_route
  11. from batch_task.batch_task import start_batch_task, stop_batch_task, execute_task, \
  12. periodically_execute
  13. from batch_task.update_llm_intent import update_llm_intent
  14. from common.exception.exception_handler import register_exception
  15. from common.log import set_customize_logfile, setup_logging, log
  16. from core.conf import settings
  17. from core.path_conf import STATIC_DIR
  18. from database.db_redis import redis_client
  19. from middleware.jwt_call_center_auth_middleware import JwtCallCenterAuthMiddleware
  20. from middleware.opera_log_middleware import OperaLogMiddleware
  21. from utils.demo_site import demo_site
  22. from utils.health_check import ensure_unique_route_names, http_limit_callback
  23. from utils.openapi import simplify_operation_ids
  24. from utils.serializers import MsgSpecJSONResponse
  25. @asynccontextmanager
  26. async def register_init(app: FastAPI):
  27. """
  28. 启动初始化
  29. :return:
  30. """
  31. # 创建数据库表
  32. # await create_table()
  33. # 连接 redis
  34. await redis_client.open()
  35. # 初始化 limiter
  36. await FastAPILimiter.init(redis_client, prefix=settings.LIMITER_REDIS_PREFIX, http_callback=http_limit_callback)
  37. yield
  38. # 关闭 redis 连接
  39. await redis_client.close()
  40. # 关闭 limiter
  41. await FastAPILimiter.close()
  42. def register_app():
  43. # FastAPI
  44. app = FastAPI(
  45. title=settings.TITLE,
  46. version=settings.VERSION,
  47. description=settings.DESCRIPTION,
  48. docs_url=settings.DOCS_URL,
  49. redoc_url=settings.REDOCS_URL,
  50. openapi_url=settings.OPENAPI_URL,
  51. default_response_class=MsgSpecJSONResponse,
  52. lifespan=register_init,
  53. )
  54. admin_app = FastAPI(
  55. title=settings.TITLE,
  56. version=settings.VERSION,
  57. description=settings.DESCRIPTION,
  58. default_response_class=MsgSpecJSONResponse,
  59. )
  60. call_center_app = FastAPI(
  61. title="Call Center", # 子应用的标题
  62. version="0.1.0", # 子应用的版本
  63. default_response_class=MsgSpecJSONResponse,
  64. )
  65. # 中间件
  66. register_call_center_middleware(call_center_app)
  67. # 路由
  68. register_router(call_center_app, call_center_route)
  69. # 分页
  70. register_page(call_center_app)
  71. # 全局异常处理
  72. register_exception(call_center_app)
  73. app.mount(f"/call_center", call_center_app)
  74. # 日志
  75. register_logger()
  76. # 静态文件
  77. register_static_file(admin_app)
  78. # 中间件
  79. register_middleware(admin_app)
  80. # 路由
  81. register_router(admin_app, route)
  82. # 分页
  83. register_page(admin_app)
  84. # 全局异常处理
  85. register_exception(admin_app)
  86. app.mount(f"{settings.API_V1_STR}/gpt", admin_app)
  87. return app
  88. def register_logger() -> None:
  89. """
  90. 系统日志
  91. :return:
  92. """
  93. setup_logging()
  94. set_customize_logfile()
  95. def register_static_file(app: FastAPI):
  96. """
  97. 静态文件交互开发模式, 生产使用 nginx 静态资源服务
  98. :param app:
  99. :return:
  100. """
  101. if settings.STATIC_FILES:
  102. import os
  103. from fastapi.staticfiles import StaticFiles
  104. if not os.path.exists(STATIC_DIR):
  105. os.mkdir(STATIC_DIR)
  106. app.mount('/static', StaticFiles(directory=STATIC_DIR), name='static')
  107. def register_middleware(app: FastAPI):
  108. """
  109. 中间件,执行顺序从下往上
  110. :param app:
  111. :return:
  112. """
  113. # Opera log
  114. # app.add_middleware(OperaLogMiddleware)
  115. # JWT auth, required
  116. # app.add_middleware(
  117. # AuthenticationMiddleware, backend=JwtAuthMiddleware(), on_error=JwtAuthMiddleware.auth_exception_handler
  118. # )
  119. # Access log
  120. if settings.MIDDLEWARE_ACCESS:
  121. from middleware.access_middleware import AccessMiddleware
  122. app.add_middleware(AccessMiddleware)
  123. # CORS: Always at the end
  124. if settings.MIDDLEWARE_CORS:
  125. from fastapi.middleware.cors import CORSMiddleware
  126. app.add_middleware(
  127. CORSMiddleware,
  128. allow_origins=['*'],
  129. allow_credentials=True,
  130. allow_methods=['*'],
  131. allow_headers=['*'],
  132. )
  133. def register_call_center_middleware(app: FastAPI):
  134. """
  135. 中间件,执行顺序从下往上
  136. :param app:
  137. :return:
  138. """
  139. # Opera log (required)
  140. app.add_middleware(OperaLogMiddleware)
  141. # JWT auth (required)
  142. app.add_middleware(
  143. AuthenticationMiddleware, backend=JwtCallCenterAuthMiddleware(), on_error=JwtCallCenterAuthMiddleware.auth_exception_handler
  144. )
  145. # Access log
  146. if settings.MIDDLEWARE_ACCESS:
  147. from middleware.access_middleware import AccessMiddleware
  148. app.add_middleware(AccessMiddleware)
  149. # CORS: Always at the end
  150. if settings.MIDDLEWARE_CORS:
  151. from fastapi.middleware.cors import CORSMiddleware
  152. app.add_middleware(
  153. CORSMiddleware,
  154. allow_origins=['*'],
  155. allow_credentials=True,
  156. allow_methods=['*'],
  157. allow_headers=['*'],
  158. )
  159. def register_router(app: FastAPI, route: APIRouter):
  160. """
  161. 路由
  162. :param app: FastAPI
  163. :param route: APIRouter
  164. :return:
  165. """
  166. dependencies = [Depends(demo_site)] if settings.DEMO_MODE else None
  167. # API
  168. app.include_router(route, dependencies=dependencies)
  169. # Extra
  170. ensure_unique_route_names(app)
  171. simplify_operation_ids(app)
  172. def register_page(app: FastAPI):
  173. """
  174. 分页查询
  175. :param app:
  176. :return:
  177. """
  178. add_pagination(app)