166 lines
5.8 KiB
Python
166 lines
5.8 KiB
Python
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
|
||
) |