deliveryman-api/app/middleware/request_logger.py
2025-03-06 15:04:10 +08:00

86 lines
2.7 KiB
Python

from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware
import time
from app.core.logger import log_request_async
from app.core.security import verify_token, decode_jwt
import json
import copy
class RequestLoggerMiddleware(BaseHTTPMiddleware):
LOGGED_METHODS = {"POST", "PUT", "DELETE"}
SENSITIVE_PATHS = {
"/api/user/login",
"/api/user/password-login",
"/api/user/reset-password"
}
SENSITIVE_FIELDS = {"password", "verify_code", "old_password", "new_password"}
def filter_sensitive_data(self, data: dict, path: str) -> dict:
"""过滤敏感数据"""
if not data or path not in self.SENSITIVE_PATHS:
return data
filtered_data = copy.deepcopy(data)
for field in self.SENSITIVE_FIELDS:
if field in filtered_data:
filtered_data[field] = "***"
return filtered_data
async def dispatch(self, request: Request, call_next):
method = request.method
if method not in self.LOGGED_METHODS:
return await call_next(request)
start_time = time.time()
path = request.url.path
headers = dict(request.headers)
query_params = dict(request.query_params)
# 获取并过滤请求体
body = None
try:
body_bytes = await request.body()
if body_bytes:
body = json.loads(body_bytes)
body = self.filter_sensitive_data(body, path)
except:
pass
# 从 Authorization 头获取 token
# token = None
# auth_header = headers.get('authorization')
# if auth_header and auth_header.startswith('Bearer '):
# token = auth_header.split(' ')[1]
# # 从 token 获取用户信息
# user_id = None
# if token:
# try:
# payload = decode_jwt(token)
# if payload:
# user_id = payload.get("phone")
# except:
# pass
# 处理请求
response = await call_next(request)
# 计算响应时间
response_time = int((time.time() - start_time) * 1000)
# 异步记录日志
log_data = {
"path": path,
"method": method,
"headers": headers,
"query_params": query_params,
"body": body,
# "user_id": user_id,
"ip_address": request.client.host,
"status_code": response.status_code,
"response_time": response_time
}
log_request_async(log_data)
return response