92 lines
3.0 KiB
Python
92 lines
3.0 KiB
Python
"""FastAPI 应用入口"""
|
||
import uuid
|
||
from contextlib import asynccontextmanager
|
||
|
||
from fastapi import FastAPI, Request
|
||
from fastapi.middleware.cors import CORSMiddleware
|
||
|
||
from app.config import settings
|
||
from app.core.response import register_exception_handlers, request_id_ctx
|
||
from app.database import engine
|
||
from app.redis_client import redis_client
|
||
|
||
|
||
@asynccontextmanager
|
||
async def lifespan(app: FastAPI):
|
||
# 周期任务(推荐激活/创作收益/超时关单),进程退出时取消
|
||
from app.services import settle_service
|
||
|
||
tasks = settle_service.start_periodic_tasks()
|
||
yield
|
||
for t in tasks:
|
||
t.cancel()
|
||
# 关闭连接池
|
||
await redis_client.aclose()
|
||
await engine.dispose()
|
||
|
||
|
||
app = FastAPI(
|
||
title="短视频应用 API",
|
||
version="1.0.0",
|
||
lifespan=lifespan,
|
||
docs_url="/docs" if settings.app_env == "dev" else None,
|
||
redoc_url=None,
|
||
)
|
||
|
||
app.add_middleware(
|
||
CORSMiddleware,
|
||
allow_origins=["*"],
|
||
allow_credentials=True,
|
||
allow_methods=["*"],
|
||
allow_headers=["*"],
|
||
)
|
||
|
||
|
||
@app.middleware("http")
|
||
async def request_id_middleware(request: Request, call_next):
|
||
"""request_id 贯穿:优先取客户端 X-Request-ID,否则生成"""
|
||
rid = request.headers.get("X-Request-ID") or str(uuid.uuid4())
|
||
request_id_ctx.set(rid)
|
||
response = await call_next(request)
|
||
response.headers["X-Request-ID"] = rid
|
||
return response
|
||
|
||
|
||
register_exception_handlers(app)
|
||
|
||
|
||
@app.get("/health", include_in_schema=False)
|
||
async def health() -> dict:
|
||
return {"status": "ok"}
|
||
|
||
|
||
# 本地文件存储(开发环境):/static 访问 server/uploads
|
||
from fastapi.staticfiles import StaticFiles
|
||
|
||
from app.config import BASE_DIR
|
||
|
||
(BASE_DIR / "uploads").mkdir(parents=True, exist_ok=True)
|
||
app.mount("/static", StaticFiles(directory=BASE_DIR / "uploads"), name="static")
|
||
|
||
# 业务路由(按模块逐步注册)
|
||
from app.api.v1 import admin, auth, common, incentives, interactions, invite, media, membership, payments, users, videos
|
||
|
||
app.include_router(media.router, prefix="/api/v1")
|
||
app.include_router(auth.router, prefix="/api/v1")
|
||
app.include_router(users.router, prefix="/api/v1")
|
||
app.include_router(videos.router, prefix="/api/v1")
|
||
app.include_router(videos.router_tags, prefix="/api/v1")
|
||
app.include_router(videos.router_search, prefix="/api/v1")
|
||
app.include_router(interactions.router_videos, prefix="/api/v1")
|
||
app.include_router(interactions.router_comments, prefix="/api/v1")
|
||
app.include_router(membership.router, prefix="/api/v1")
|
||
app.include_router(payments.router, prefix="/api/v1")
|
||
app.include_router(payments.router_callbacks, prefix="/api/v1")
|
||
app.include_router(incentives.router_referral, prefix="/api/v1")
|
||
app.include_router(incentives.router_assets, prefix="/api/v1")
|
||
app.include_router(common.router, prefix="/api/v1")
|
||
app.include_router(admin.router, prefix="/api/v1")
|
||
app.include_router(invite.router, prefix="/api/v1")
|
||
# 推广落地页(根路径 /r/{code},对应 referral/me 返回的 invite_url)
|
||
app.include_router(invite.router_page)
|