Files
shanxia2.0/backend/app/main.py
T
2026-05-12 22:07:53 +08:00

97 lines
2.6 KiB
Python

"""FastAPI 应用入口(骨架工程)"""
from contextlib import asynccontextmanager
import logging
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.core.config import settings
from app.core.database import SessionLocal
from app.core.api_request_log_middleware import ApiRequestLogMiddleware
from app.core.api_crypto_middleware import ApiCryptoMiddleware
from app.models import models # noqa: F401
from app.api import public_router, menu_router, admin_router
@asynccontextmanager
async def lifespan(app: FastAPI):
"""应用生命周期管理"""
from app.core import login_crypto
login_crypto.ensure_initialized()
from app.tasks import init_scheduled_tasks
try:
init_scheduled_tasks(SessionLocal)
except Exception as e:
logging.warning("定时任务调度器启动失败: %s", e)
yield
from app.tasks import shutdown_scheduler
try:
shutdown_scheduler()
except Exception:
pass
app = FastAPI(
title=settings.APP_NAME,
description="zkxw 管理端骨架后端(鉴权与菜单)",
version="1.0.0",
docs_url="/docs",
redoc_url="/redoc",
lifespan=lifespan,
)
_cors_kw: dict = {
"allow_origins": settings.BACKEND_CORS_ORIGINS,
"allow_credentials": True,
"allow_methods": ["*"],
"allow_headers": ["*"],
}
if settings.DEBUG:
_cors_kw["allow_origin_regex"] = r"^https?://(localhost|127\.0\.0\.1)(:\d+)?$"
app.add_middleware(CORSMiddleware, **_cors_kw)
app.add_middleware(ApiRequestLogMiddleware)
app.add_middleware(ApiCryptoMiddleware)
app.include_router(public_router, prefix=settings.API_V1_PREFIX)
app.include_router(menu_router, prefix=settings.API_V1_PREFIX)
app.include_router(admin_router, prefix=settings.API_V1_PREFIX)
logger = logging.getLogger("sqxp")
def _mask_secret(value: str) -> str:
if not value:
return "(empty)"
if len(value) <= 6:
return "*" * len(value)
return f"{value[:3]}***{value[-3:]}"
_api_crypto_boot_msg = (
"API_CRYPTO_BOOT "
f"enabled={settings.API_ENCRYPT_ENABLED} "
f"fail_open={settings.API_ENCRYPT_FAIL_OPEN} "
f"fixed_secret={_mask_secret(settings.API_ENCRYPT_FIXED_SECRET)} "
f"ts_skew_sec={settings.API_ENCRYPT_TS_SKEW_SEC} "
f"nonce_ttl_sec={settings.API_ENCRYPT_NONCE_TTL_SEC} "
f"exclude_count={len([x for x in (settings.API_ENCRYPT_EXCLUDE_PATHS or '').split(',') if x.strip()])}"
)
print(_api_crypto_boot_msg)
logger.info(_api_crypto_boot_msg)
@app.get("/")
def root():
return {"name": settings.APP_NAME, "version": "1.0.0", "docs": "/docs"}
@app.get("/health")
def health_check():
return {"status": "healthy"}