Files
ESP32_GDEY042T81_server/main.py
jeremygan2021 9620a4138d AI生图
2026-03-02 12:53:36 +08:00

172 lines
4.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from fastapi.openapi.utils import get_openapi
from starlette.middleware.sessions import SessionMiddleware
from contextlib import asynccontextmanager
import logging
import os
from config import settings
from database import init_db
from mqtt_manager import mqtt_manager
from api import api_router
from admin_routes import admin_router
from auth import APIKeyMiddleware, AdminAuthMiddleware
# 配置日志
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
# 启动时执行
logger.info("正在启动墨水屏桌面屏幕系统服务端...")
# 初始化数据库
try:
init_db()
logger.info("数据库初始化完成")
except Exception as e:
logger.error(f"数据库初始化失败: {str(e)}")
# 连接MQTT代理
try:
mqtt_manager.connect()
logger.info("MQTT连接已启动")
except Exception as e:
logger.error(f"MQTT连接失败: {str(e)}")
# 确保静态文件目录存在
os.makedirs(settings.static_dir, exist_ok=True)
os.makedirs(settings.media_dir, exist_ok=True)
yield
# 关闭时执行
logger.info("正在关闭墨水屏桌面屏幕系统服务端...")
# 断开MQTT连接
mqtt_manager.disconnect()
logger.info("MQTT连接已断开")
# 创建FastAPI应用
app = FastAPI(
title="墨水屏桌面屏幕系统 API",
description="用于管理墨水屏设备、内容和待办事项的API",
version="1.0.0",
lifespan=lifespan,
)
# 自定义OpenAPI模式以显示API Key鉴权按钮
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title=app.title,
version=app.version,
description=app.description,
routes=app.routes,
)
# 添加安全方案
if "components" not in openapi_schema:
openapi_schema["components"] = {}
security_scheme = {
"type": "apiKey",
"in": "header",
"name": "X-API-Key",
"description": "API Key鉴权请在下方输入正确的API Key"
}
if "securitySchemes" not in openapi_schema["components"]:
openapi_schema["components"]["securitySchemes"] = {}
openapi_schema["components"]["securitySchemes"]["APIKeyHeader"] = security_scheme
# 添加全局安全要求
if "security" not in openapi_schema:
openapi_schema["security"] = []
# 避免重复添加
has_apikey_security = False
for security_req in openapi_schema["security"]:
if "APIKeyHeader" in security_req:
has_apikey_security = True
break
if not has_apikey_security:
openapi_schema["security"].append({"APIKeyHeader": []})
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi
# 添加CORS中间件
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 在生产环境中应该设置具体的允许来源
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 添加API Key鉴权中间件
app.add_middleware(APIKeyMiddleware)
# 添加Admin认证中间件
app.add_middleware(AdminAuthMiddleware)
# 添加Session中间件
app.add_middleware(SessionMiddleware, secret_key=settings.secret_key)
# 挂载静态文件
app.mount("/static", StaticFiles(directory=settings.static_dir), name="static")
app.mount("/media", StaticFiles(directory=settings.media_dir), name="media")
# 注册API路由
app.include_router(api_router, prefix="/api")
# 包含管理后台路由
app.include_router(admin_router, prefix="/admin", tags=["管理后台"])
# 根路径
@app.get("/")
async def root():
return {
"message": "墨水屏桌面屏幕系统服务端",
"version": "1.0.0",
"docs": "/docs",
"redoc": "/redoc"
}
# 健康检查
@app.get("/health")
async def health_check():
return {
"status": "healthy",
"mqtt_connected": mqtt_manager.connected
}
# 中间件:记录请求日志
@app.middleware("http")
async def log_requests(request: Request, call_next):
logger.info(f"请求: {request.method} {request.url}")
response = await call_next(request)
logger.info(f"响应状态码: {response.status_code}")
return response
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"main:app",
host="0.0.0.0",
port=9999,
reload=settings.debug
)