-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathapp_factory.py
More file actions
59 lines (47 loc) · 1.78 KB
/
app_factory.py
File metadata and controls
59 lines (47 loc) · 1.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import os.path
import tomllib
from contextlib import asynccontextmanager
from typing import Callable, Awaitable
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse, Response
from common import project_root
from common.exception import CommonException
async def exception_handler(_: Request, e: Exception) -> Response:
if isinstance(e, CommonException):
return JSONResponse(
status_code=e.code, content={"code": e.code, "error": e.error}
)
return JSONResponse(
status_code=500,
content={"code": 500, "error": CommonException.parse_exception(e)},
)
def app_factory(
startup_funcs: list[Callable[..., Awaitable]] | None = None,
shutdown_funcs: list[Callable[..., Awaitable]] | None = None,
version: str | None = None,
patch_funcs: list[Callable[[FastAPI], None]] | None = None,
) -> FastAPI:
@asynccontextmanager
async def lifespan(fastapi: FastAPI):
for startup_func in startup_funcs or []:
await startup_func(fastapi)
yield
for shutdown_func in shutdown_funcs or []:
await shutdown_func(fastapi)
project_file: str = "pyproject.toml"
if version is None and os.path.exists(project_root.path(project_file)):
with project_root.open(project_file, "rb") as f:
version = tomllib.load(f)["project"]["version"]
app = FastAPI(lifespan=lifespan, version=version)
for patch_func in patch_funcs or []:
patch_func(app)
app.add_middleware(
CORSMiddleware, # noqa
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.add_exception_handler(Exception, exception_handler)
return app