xiangqinxiaochengxu/backend/app/main.py

102 lines
3.1 KiB
Python
Raw Permalink Normal View History

2026-04-17 19:26:32 +08:00
from pathlib import Path
2026-04-17 10:49:14 +08:00
from fastapi import FastAPI, HTTPException, Request
from fastapi.exceptions import RequestValidationError
from fastapi.middleware.cors import CORSMiddleware
2026-05-18 14:24:55 +08:00
from fastapi.responses import HTMLResponse, JSONResponse
2026-04-17 19:26:32 +08:00
from fastapi.staticfiles import StaticFiles
2026-04-17 10:49:14 +08:00
from app.config import settings
from app.routers import api_router
2026-05-18 14:24:55 +08:00
from app.routers.activities import activity_share_landing
2026-04-17 10:49:14 +08:00
def create_app() -> FastAPI:
app = FastAPI(title=settings.app_name, debug=settings.app_debug)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/health", tags=["health"])
async def health_check() -> dict[str, str]:
return {"status": "ok"}
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse:
_ = request
code_map = {
400: 1005,
401: 1001,
403: 1002,
404: 1003,
}
return JSONResponse(
status_code=exc.status_code,
content={
"code": code_map.get(exc.status_code, 1005),
"message": exc.detail,
"data": None,
},
)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(
request: Request, exc: RequestValidationError
) -> JSONResponse:
_ = request
field_errors = []
for error in exc.errors():
location = error.get("loc", [])
field_name = location[-1] if location else "unknown"
field_errors.append(
{
"field": field_name,
"message": error.get("msg", "参数校验失败"),
"type": error.get("type"),
}
)
return JSONResponse(
status_code=422,
content={
"code": 1004,
"message": "参数校验失败",
"data": {"field_errors": field_errors},
},
)
@app.exception_handler(Exception)
async def generic_exception_handler(request: Request, exc: Exception) -> JSONResponse:
_ = request
return JSONResponse(
status_code=500,
content={
"code": 1005,
"message": str(exc) if settings.app_debug else "服务器内部错误",
"data": None,
},
)
2026-04-17 19:26:32 +08:00
static_dir = Path(__file__).resolve().parent / "static"
static_dir.mkdir(parents=True, exist_ok=True)
app.mount("/static", StaticFiles(directory=static_dir), name="static")
2026-06-18 23:06:40 +08:00
app.mount(f"{settings.api_v1_prefix}/static", StaticFiles(directory=static_dir), name="api-static")
2026-04-17 19:26:32 +08:00
2026-05-18 14:24:55 +08:00
app.add_api_route(
"/share/activity/{share_token}",
activity_share_landing,
methods=["GET"],
response_class=HTMLResponse,
include_in_schema=False,
)
2026-04-17 10:49:14 +08:00
app.include_router(api_router, prefix=settings.api_v1_prefix)
return app
app = create_app()