Files
full-stack-doc/backend/main.py
2025-10-14 20:05:29 +08:00

166 lines
5.8 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
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
import sys
import os
from pathlib import Path
from datetime import datetime
# 处理PyInstaller打包后的资源路径
def get_resource_path(relative_path: str) -> str:
"""获取资源文件的绝对路径,兼容开发环境和打包环境"""
try:
# PyInstaller创建的临时文件夹路径
base_path = sys._MEIPASS
except AttributeError:
# 正常的开发环境
base_path = os.path.dirname(os.path.abspath(__file__))
return os.path.join(base_path, relative_path)
# 确保app模块可以正确导入
def setup_app_imports():
"""设置模块导入路径确保打包后能正确导入app模块"""
current_dir = os.path.dirname(os.path.abspath(__file__))
if current_dir not in sys.path:
sys.path.insert(0, current_dir)
# 如果是打包后的环境添加MEIPASS到sys.path
if hasattr(sys, '_MEIPASS'):
meipass = sys._MEIPASS
if meipass not in sys.path:
sys.path.insert(0, meipass)
# 设置导入路径
setup_app_imports()
from app.core.config import settings
from app.api.v1.endpoints import health, auth, files
# 简单的日志打印函数
def log_info(message):
"""打印INFO级别日志"""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"[{timestamp}] INFO: {message}")
def log_error(message):
"""打印ERROR级别日志"""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"[{timestamp}] ERROR: {message}")
def log_debug(message):
"""打印DEBUG级别日志"""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"[{timestamp}] DEBUG: {message}")
from fastapi import Request
import json
async def log_requests_middleware(request: Request, call_next):
"""记录所有API请求的入参不消耗请求体"""
start_time = datetime.now()
# 获取请求基本信息
method = request.method
url = str(request.url)
client_ip = request.client.host if request.client else "unknown"
# 立即打印基本信息
print(f"[{start_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: === API请求开始 ===")
print(f"[{start_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: 方法: {method}")
print(f"[{start_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: URL: {url}")
print(f"[{start_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: 客户端IP: {client_ip}")
# 获取查询参数
query_params = dict(request.query_params)
if query_params:
print(f"[{start_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: 查询参数: {query_params}")
else:
print(f"[{start_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: 查询参数: 无")
# 获取请求头信息(只记录非敏感信息)
content_type = request.headers.get("content-type", "")
content_length = request.headers.get("content-length", "")
user_agent = request.headers.get("user-agent", "")
print(f"[{start_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: Content-Type: {content_type}")
if content_length:
print(f"[{start_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: Content-Length: {content_length}字节")
print(f"[{start_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: User-Agent: {user_agent}")
# 注意:这里不读取请求体,避免消耗它
if method in ["POST", "PUT", "PATCH"]:
print(f"[{start_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: 请求体: 将在路由处理函数中记录")
print(f"[{start_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: === 开始处理请求 ===")
# 处理请求
try:
response = await call_next(request)
# 记录响应信息
end_time = datetime.now()
duration = (end_time - start_time).total_seconds()
print(f"[{end_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: === 请求处理完成 ===")
print(f"[{end_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: 状态码: {response.status_code}")
print(f"[{end_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: 处理耗时: {duration:.3f}")
print(f"[{end_time.strftime('%Y-%m-%d %H:%M:%S')}] INFO: === 响应记录完成 ===")
return response
except Exception as e:
end_time = datetime.now()
duration = (end_time - start_time).total_seconds()
print(f"[{end_time.strftime('%Y-%m-%d %H:%M:%S')}] ERROR: === 请求处理出错 ===")
print(f"[{end_time.strftime('%Y-%m-%d %H:%M:%S')}] ERROR: 错误: {str(e)}")
print(f"[{end_time.strftime('%Y-%m-%d %H:%M:%S')}] ERROR: 处理耗时: {duration:.3f}")
raise
# 确保logs目录存在
logs_dir = get_resource_path("logs")
os.makedirs(logs_dir, exist_ok=True)
# 打印启动信息
log_info("=== Server Starting ===")
log_info(f"Python version: {sys.version}")
log_info(f"Working directory: {os.getcwd()}")
log_info("Simple print logger configured")
app = FastAPI(
title="云盘应用 API",
description="现代化的云存储Web应用后端API",
version="1.0.0",
docs_url="/docs",
redoc_url="/redoc"
)
# 添加请求日志中间件在CORS之前
app.middleware("http")(log_requests_middleware)
# CORS中间件
app.add_middleware(
CORSMiddleware,
allow_origins=settings.ALLOWED_HOSTS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 包含路由
app.include_router(health.router, prefix="/api/v1", tags=["health"])
app.include_router(auth.router, prefix="/api/v1/auth", tags=["authentication"])
app.include_router(files.router, prefix="/api/v1/files", tags=["files"])
@app.get("/")
async def root():
return {"message": "云盘应用 API", "version": "1.0.1"}
if __name__ == "__main__":
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8002,
reload=True if settings.ENVIRONMENT == "development" else False
)