aicheckv2-api/core/middleware.py

158 lines
5.5 KiB
Python
Raw Normal View History

2025-04-11 08:54:28 +08:00
# -*- coding: utf-8 -*-
# @version : 1.0
# @Create Time : 2021/10/19 15:47
# @File : middleware.py
# @IDE : PyCharm
# @desc : 中间件
"""
官方文档中间件https://fastapi.tiangolo.com/tutorial/middleware/
官方文档高级中间件https://fastapi.tiangolo.com/advanced/middleware/
"""
import datetime
import json
import time
from fastapi import Request, Response
from core.logger import logger
from fastapi import FastAPI
from fastapi.routing import APIRoute
from user_agents import parse
from application.settings import OPERATION_RECORD_METHOD, MONGO_DB_ENABLE, IGNORE_OPERATION_FUNCTION, \
DEMO_WHITE_LIST_PATH, DEMO, DEMO_BLACK_LIST_PATH
from utils.response import ErrorResponse
from apps.vadmin.record.crud import OperationRecordDal
from core.database import mongo_getter
from utils import status
def write_request_log(request: Request, response: Response):
http_version = f"http/{request.scope['http_version']}"
content_length = response.raw_headers[0][1]
process_time = response.headers["X-Process-Time"]
content = f"basehttp.log_message: '{request.method} {request.url} {http_version}' {response.status_code}" \
f"{response.charset} {content_length} {process_time}"
logger.info(content)
def register_request_log_middleware(app: FastAPI):
"""
记录请求日志中间件
:param app:
:return:
"""
@app.middleware("http")
async def request_log_middleware(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
write_request_log(request, response)
return response
def register_operation_record_middleware(app: FastAPI):
"""
操作记录中间件
用于将使用认证的操作全部记录到 mongodb 数据库中
:param app:
:return:
"""
@app.middleware("http")
async def operation_record_middleware(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
if not MONGO_DB_ENABLE:
return response
telephone = request.scope.get('telephone', None)
user_id = request.scope.get('user_id', None)
user_name = request.scope.get('user_name', None)
route = request.scope.get('route')
if not telephone:
return response
elif request.method not in OPERATION_RECORD_METHOD:
return response
elif route.name in IGNORE_OPERATION_FUNCTION:
return response
process_time = time.time() - start_time
user_agent = parse(request.headers.get("user-agent"))
system = f"{user_agent.os.family} {user_agent.os.version_string}"
browser = f"{user_agent.browser.family} {user_agent.browser.version_string}"
query_params = dict(request.query_params.multi_items())
path_params = request.path_params
if isinstance(request.scope.get('body'), str):
body = request.scope.get('body')
else:
body = request.scope.get('body').decode()
if body:
body = json.loads(body)
params = {
"body": body,
"query_params": query_params if query_params else None,
"path_params": path_params if path_params else None,
}
content_length = response.raw_headers[0][1]
assert isinstance(route, APIRoute)
document = {
"process_time": process_time,
"telephone": telephone,
"user_id": user_id,
"user_name": user_name,
"request_api": request.url.__str__(),
"client_ip": request.client.host,
"system": system,
"browser": browser,
"request_method": request.method,
"api_path": route.path,
"summary": route.summary,
"description": route.description,
"tags": route.tags,
"route_name": route.name,
"status_code": response.status_code,
"content_length": content_length,
"create_datetime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"params": json.dumps(params)
}
await OperationRecordDal(mongo_getter(request)).create_data(document)
return response
def register_demo_env_middleware(app: FastAPI):
"""
演示环境中间件
:param app:
:return:
"""
@app.middleware("http")
async def demo_env_middleware(request: Request, call_next):
path = request.scope.get("path")
if request.method != "GET":
print("路由:", path, request.method)
if DEMO and request.method != "GET":
if path in DEMO_BLACK_LIST_PATH:
return ErrorResponse(
status=status.HTTP_403_FORBIDDEN,
code=status.HTTP_403_FORBIDDEN,
msg="演示环境,禁止操作"
)
elif path not in DEMO_WHITE_LIST_PATH:
return ErrorResponse(msg="演示环境,禁止操作")
return await call_next(request)
def register_jwt_refresh_middleware(app: FastAPI):
"""
JWT刷新中间件
:param app:
:return:
"""
@app.middleware("http")
async def jwt_refresh_middleware(request: Request, call_next):
response = await call_next(request)
refresh = request.scope.get('if-refresh', 0)
response.headers["if-refresh"] = str(refresh)
return response