aicheckv2-api/core/middleware.py
2025-04-11 08:54:28 +08:00

158 lines
5.5 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.

# -*- 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