mirror of
https://github.com/ZhuLinsen/daily_stock_analysis
synced 2026-09-20 10:53:33 +08:00
* feat(web): add FastAPI & React web connect * feat: add FastAPI package * feat: system base struct * feat: frontend base struct * feat: 基础分析接口,历史记录接口 * fix: 使用正确的 FastAPI 方法定义,避免线程阻塞 * fix: 对接历史报告页、详情页 * fix: 修复接口问题 * fix: 网络配置 允许公网访问 跨域配置 * fix: 页面打包 & 提供 Server 静态访问 * fix: 优化dock栏样式 * fix: 优化图标样式 * fix: 修改部分配色 * fix: 删除垃圾文档 * fix: 删除垃圾代码 * fix: 驼峰转换工具 * fix: 历史记录列表滚动加载(分页) * feat: 显示分析中任务 * fix: 调整布局 * fix: 优化 Market Sentiment 组件动效 * fix: 历史列表组件bug * fix: FastAPI 日志配置 * feat: 新闻历史接口 * feat: 资讯列表 * feat: 优化布局 * fix: 修复页面元素变宽问题 * fix: 中文标题 * fix: 任务列表状态显示问题 * fix: 抽取日志配置 * fix: 优化报告价格显示 * fix: 修复编译错误 * fix: FastAPI 启动提取到 main.py * fix: 补充新web-ui启动文档 * fix: 默认发送通知 * fix: FastAPI 模式适配 docker * fix: FastAPI 模式文档 * Update api/v1/endpoints/stocks.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: package-lock.json * fix: 修改错别字 * fix: 更新文档说明 * fix: 更新文档说明 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
129 lines
3.7 KiB
Python
129 lines
3.7 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
===================================
|
||
全局异常处理中间件
|
||
===================================
|
||
|
||
职责:
|
||
1. 捕获未处理的异常
|
||
2. 统一错误响应格式
|
||
3. 记录错误日志
|
||
"""
|
||
|
||
import logging
|
||
import traceback
|
||
from typing import Callable
|
||
|
||
from fastapi import Request, Response
|
||
from fastapi.responses import JSONResponse
|
||
from starlette.middleware.base import BaseHTTPMiddleware
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
class ErrorHandlerMiddleware(BaseHTTPMiddleware):
|
||
"""
|
||
全局异常处理中间件
|
||
|
||
捕获所有未处理的异常,返回统一格式的错误响应
|
||
"""
|
||
|
||
async def dispatch(
|
||
self,
|
||
request: Request,
|
||
call_next: Callable
|
||
) -> Response:
|
||
"""
|
||
处理请求,捕获异常
|
||
|
||
Args:
|
||
request: 请求对象
|
||
call_next: 下一个处理器
|
||
|
||
Returns:
|
||
Response: 响应对象
|
||
"""
|
||
try:
|
||
response = await call_next(request)
|
||
return response
|
||
|
||
except Exception as e:
|
||
# 记录错误日志
|
||
logger.error(
|
||
f"未处理的异常: {e}\n"
|
||
f"请求路径: {request.url.path}\n"
|
||
f"请求方法: {request.method}\n"
|
||
f"堆栈: {traceback.format_exc()}"
|
||
)
|
||
|
||
# 返回统一格式的错误响应
|
||
return JSONResponse(
|
||
status_code=500,
|
||
content={
|
||
"error": "internal_error",
|
||
"message": "服务器内部错误,请稍后重试",
|
||
"detail": str(e) if logger.isEnabledFor(logging.DEBUG) else None
|
||
}
|
||
)
|
||
|
||
|
||
def add_error_handlers(app) -> None:
|
||
"""
|
||
添加全局异常处理器
|
||
|
||
为 FastAPI 应用添加各类异常的处理器
|
||
|
||
Args:
|
||
app: FastAPI 应用实例
|
||
"""
|
||
from fastapi import HTTPException
|
||
from fastapi.exceptions import RequestValidationError
|
||
|
||
@app.exception_handler(HTTPException)
|
||
async def http_exception_handler(request: Request, exc: HTTPException):
|
||
"""处理 HTTP 异常"""
|
||
# 如果 detail 已经是 ErrorResponse 格式的 dict,直接使用
|
||
if isinstance(exc.detail, dict) and "error" in exc.detail and "message" in exc.detail:
|
||
return JSONResponse(
|
||
status_code=exc.status_code,
|
||
content=exc.detail
|
||
)
|
||
# 否则将 detail 包装成 ErrorResponse 格式
|
||
return JSONResponse(
|
||
status_code=exc.status_code,
|
||
content={
|
||
"error": "http_error",
|
||
"message": str(exc.detail) if exc.detail else "HTTP Error",
|
||
"detail": None
|
||
}
|
||
)
|
||
|
||
@app.exception_handler(RequestValidationError)
|
||
async def validation_exception_handler(request: Request, exc: RequestValidationError):
|
||
"""处理请求验证异常"""
|
||
return JSONResponse(
|
||
status_code=422,
|
||
content={
|
||
"error": "validation_error",
|
||
"message": "请求参数验证失败",
|
||
"detail": exc.errors()
|
||
}
|
||
)
|
||
|
||
@app.exception_handler(Exception)
|
||
async def general_exception_handler(request: Request, exc: Exception):
|
||
"""处理通用异常"""
|
||
logger.error(
|
||
f"未处理的异常: {exc}\n"
|
||
f"请求路径: {request.url.path}\n"
|
||
f"堆栈: {traceback.format_exc()}"
|
||
)
|
||
return JSONResponse(
|
||
status_code=500,
|
||
content={
|
||
"error": "internal_error",
|
||
"message": "服务器内部错误",
|
||
"detail": None
|
||
}
|
||
)
|