Paddlex服务化代理处理跨域、替换Response中Json key

背景

前端直接调用paddlex serve服务时,由于前端会发送OPTIONS请求,paddlex默认会拒绝跨域请求。

另外由于前端限制,需要把Response中errorCode、errorMsg替换成code、message。

方案

Nginx

通过 Nginx 的 sub_filter 或 OpenResty 的 Lua 脚本修改 JSON 键名(适用于简单替换)。

Nginx是替换,存在把正常的内容替换的情况,不推荐。

Nginx 配置示例:

nginx 复制代码
server {
    listen 80;
    server_name your_domain.com;

    location /predict {
        proxy_pass http://localhost:8000;  # PaddleX 服务地址
        sub_filter '"errorCode":' '"code":';  # 替换字段
        sub_filter '"errorMsg":' '"message":';
        sub_filter '"result":' '"data":';
        sub_filter_once off;
        sub_filter_types application/json;
    }
}

修改配置后重载 Nginx:

bash 复制代码
sudo nginx -t && sudo systemctl reload nginx

uvicorn(Python代理)

Uvicorn 作为一款基于异步 I/O 的 ASGI 服务器,在高并发场景下表现优异,但其性能也受到配置、应用逻辑、硬件资源等因素影响。

1.编写代理

新建proxy.py文件:

python 复制代码
from fastapi import FastAPI, Request, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
import requests
import logging

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = FastAPI()

# 跨域配置
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

PADDLEX_SERVER = "http://localhost:8080"

@app.post("/ocr")
async def predict(request: Request):
    try:
        # 1. 获取客户端请求体
        client_json = await request.json()
        
        # 2. 转发请求到 PaddleX 服务
        response = requests.post(
            f"{PADDLEX_SERVER}/ocr",
            json=client_json,
            timeout=30  # 添加超时控制
        )
        response.raise_for_status()  # 自动抛出 HTTP 错误
        
        # 3. 处理原始响应数据
        try:
            response_data = response.json()
        except requests.exceptions.JSONDecodeError:
            logger.error("PaddleX 返回了非 JSON 响应")
            raise HTTPException(502, "后端服务响应格式错误")

        # 4. 字段替换逻辑
        if "errorCode" in response_data:
            response_data["code"] = response_data.pop("errorCode")
        if "errorMsg" in response_data:
            response_data["message"] = response_data.pop("errorMsg")
        if "result" in response_data:
            response_data["data"] = response_data.pop("result")
        if "code" in response_data and response_data["code"] == 0:
            response_data["code"] = 200

        # 5. 返回修改后的响应(移除 Content-Length 头)
        headers = dict(response.headers)
        headers.pop("Content-Length", None)  # 删除原始 Content-Length
        headers.pop("content-length", None)  # 小写 key 兼容
        headers.pop("server", None)  # 小写 key 兼容
        headers.pop("date", None)  # 小写 key 兼容
        
        return JSONResponse(
            content=response_data,
            status_code=response.status_code,
            headers=headers
        )

    except requests.exceptions.RequestException as e:
        logger.error(f"请求后端服务失败: {str(e)}")
        raise HTTPException(504, f"后端服务通信失败: {str(e)}")
    except Exception as e:
        logger.error(f"未知错误: {str(e)}")
        raise HTTPException(500, "服务器内部错误")

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8090)
2.启动代理
bash 复制代码
nohup python paddleImageOcrProxy.py > paddleImageOcrProxy.log 2>&1 &

查看日志:

bash 复制代码
$  tail -fn 200 paddleImageOcrProxy.log
INFO:     Started server process [18566]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8090 (Press CTRL+C to quit)
INFO:     10.90.201.61:10346 - "POST /ocr HTTP/1.1" 200 OK
INFO:     10.90.201.61:10357 - "POST /ocr HTTP/1.1" 200 OK
INFO:     10.90.201.61:10357 - "POST /ocr HTTP/1.1" 200 OK
INFO:     10.90.200.182:52519 - "OPTIONS /ocr HTTP/1.1" 200 OK
INFO:     10.90.200.182:52519 - "POST /ocr HTTP/1.1" 200 OK
相关推荐
沐硕4 小时前
《基于改进协同过滤与多目标优化的健康饮食推荐系统设计与实现》
java·python·算法·fastapi·多目标优化·饮食推荐·改进协同过滤
奔跑的呱呱牛5 小时前
arcgis-to-geojson双向转换工具库
arcgis·json
带娃的IT创业者5 小时前
WeClaw 架构演进史:从 0 到 1 构建跨平台 AI 助手的完整历程
人工智能·python·websocket·架构·fastapi·架构设计·实时通信
武超杰7 小时前
SpringMVC核心功能详解:从RESTful到JSON数据处理
后端·json·restful
沐硕11 小时前
Dietify 智能饮食推荐系统全解析 —— 当协同过滤遇上营养科学,构建你的私人饮食管家
spring boot·python·fastapi·多目标优化·饮食推荐·改进协同过滤
Blurpath住宅代理1 天前
原生IP vs 广播IP:如何从网络层判断代理IP的“真实性”?
网络·静态ip·动态ip·代理·代理ip·住宅ip·住宅代理
还是大剑师兰特1 天前
Vue3 前端专属配置(VSCode settings.json + .prettierrc)
前端·vscode·json
带娃的IT创业者1 天前
WeClaw WebSocket 连接中断诊断:从频繁掉线到稳定长连的优化之路
python·websocket·网络协议·php·fastapi·实时通信
qq_283720051 天前
Cesium实战(三):加载天地图(影像图,注记图)避坑指南
json·gis·cesium
雷帝木木1 天前
Flutter for OpenHarmony:Flutter 三方库 cbor 构建 IoT 设备的极致压缩防窃协议(基于标准二进制 JSON 表达格式)
网络·物联网·flutter·http·json·harmonyos·鸿蒙