"""FastAPI 应用入口""" from fastapi import FastAPI, Request, Response from fastapi.middleware.cors import CORSMiddleware from starlette.middleware.base import BaseHTTPMiddleware from app.config import settings from app.logging_config import setup_logging from app.middleware.rate_limit import RateLimitMiddleware from app.api import health, auth, upload, scripts, videos, tasks, rules, ai_config, sse, projects, briefs, organizations, dashboard, export # Initialize logging logger = setup_logging() # 环境判断 _is_production = settings.ENVIRONMENT == "production" # 创建应用(生产环境禁用 API 文档) app = FastAPI( title=settings.APP_NAME, version=settings.APP_VERSION, description="AI 营销内容合规审核平台 API", docs_url=None if _is_production else "/docs", redoc_url=None if _is_production else "/redoc", ) # CORS 配置(从环境变量读取允许的来源) _cors_origins = [ origin.strip() for origin in settings.CORS_ORIGINS.split(",") if origin.strip() ] app.add_middleware( CORSMiddleware, allow_origins=_cors_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Security headers middleware class SecurityHeadersMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next) -> Response: response = await call_next(request) response.headers["X-Content-Type-Options"] = "nosniff" response.headers["X-Frame-Options"] = "DENY" response.headers["X-XSS-Protection"] = "1; mode=block" response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin" if _is_production: response.headers["Strict-Transport-Security"] = ( "max-age=63072000; includeSubDomains; preload" ) return response app.add_middleware(SecurityHeadersMiddleware) # Rate limiting app.add_middleware(RateLimitMiddleware, default_limit=60, window_seconds=60) # 注册路由 app.include_router(health.router, prefix="/api/v1") app.include_router(auth.router, prefix="/api/v1") app.include_router(upload.router, prefix="/api/v1") app.include_router(scripts.router, prefix="/api/v1") app.include_router(videos.router, prefix="/api/v1") app.include_router(tasks.router, prefix="/api/v1") app.include_router(rules.router, prefix="/api/v1") app.include_router(ai_config.router, prefix="/api/v1") app.include_router(sse.router, prefix="/api/v1") app.include_router(projects.router, prefix="/api/v1") app.include_router(briefs.router, prefix="/api/v1") app.include_router(organizations.router, prefix="/api/v1") app.include_router(dashboard.router, prefix="/api/v1") app.include_router(export.router, prefix="/api/v1") @app.on_event("startup") async def startup_event(): logger.info(f"Starting {settings.APP_NAME} v{settings.APP_VERSION}") @app.get("/") async def root(): """根路径""" return { "message": f"Welcome to {settings.APP_NAME}", "version": settings.APP_VERSION, "docs": "disabled" if _is_production else "/docs", }