ahserver/aidocs/proxyProcessor.md
2025-10-05 12:07:12 +08:00

6.5 KiB
Raw Blame History

以下是为提供的 Python 代码编写的 Markdown 格式技术文档,适用于项目内部或开发者参考。


ProxyProcessor 技术文档

概述

ProxyProcessor 是一个基于 aiohttp 的异步代理处理器类,继承自 BaseProcessor。它用于将 HTTP 请求转发到目标 URL并以流式方式返回响应内容支持动态 URL 渲染、身份认证、请求头注入和参数传递等功能。

该处理器适用于需要在服务端代理外部 API 请求的场景,尤其适合结合模板引擎动态生成请求配置。


模块依赖

import aiohttp
from appPublic.log import info, debug, warning, error, critical, exception
from aiohttp import web, BasicAuth
from aiohttp import client
from .baseProcessor import *

⚠️ 注意:原代码中存在拼写错误(如 paams 应为 params)和潜在变量名错误(如 g.get('headers') 应为 d.get('headers')),已在文档中修正并标注。


类定义

class ProxyProcessor(BaseProcessor)

继承自 BaseProcessor,实现了一个可识别的处理器插件机制,并提供代理功能。

方法:isMe(name: str) -> bool

判断当前处理器是否匹配给定名称。

参数:
  • name (str): 处理器名称标识
返回值:
  • True 当且仅当 name == 'proxy'
  • 否则返回 False
示例:
if ProxyProcessor.isMe("proxy"):
    # 使用此处理器

核心方法

async path_call(self, request: web.Request, params: dict = {}) -> dict

根据请求和参数生成代理请求的目标地址及相关配置数据,通过模板引擎渲染后解析为 JSON 对象。

参数:
  • request (aiohttp.web.Request): 当前 HTTP 请求对象
  • params (dict, optional): 额外传入的参数,默认为空字典
流程说明:
  1. 设置运行环境(调用 set_run_env
  2. 获取路径(优先使用 params['path'],否则使用 request.path
  3. 构建完整目标 URL通过 self.resource.entireUrl()
  4. 更新运行命名空间(run_ns)包含传入参数
  5. 使用模板引擎(tmpl_engine)渲染 URL 字符串
  6. 解析渲染结果为 JSON 数据并返回
返回值:
  • dict: 包含代理请求所需信息的对象,例如:
    {
      "url": "https://api.example.com/data",
      "method": "GET",
      "user": "admin",
      "password": "secret",
      "headers": { "X-Custom": "value" },
      "params": { "page": 1 }
    }
    
日志输出:
  • 调试日志记录渲染后的数据内容。

🔍 提示:te.render() 支持 Jinja2 或类似语法模板,可用于动态构造请求参数。


async def datahandle(self, request: web.Request) -> web.StreamResponse

核心代理处理函数,执行对外部服务的实际请求,并以流式方式转发响应。

参数:
  • request (web.Request): 客户端原始请求
功能流程:
  1. 读取代理配置

    • 调用 path_call() 获取代理请求配置 d
  2. 构建请求头

    • 复制原始请求头 → reqH
    • 若配置中包含 userpassword,创建 BasicAuth 实例
    • 若配置中有 headers,将其合并到请求头中(⚠️ 原代码有误,已修正)
  3. 准备查询参数

    • 若配置中包含 params,提取用于 GET 查询参数
  4. 发起异步请求

    • 使用 aiohttp.client.request() 发起请求
    • 方法默认为客户端请求方法(如 GET/POST可被配置覆盖
    • 禁用自动重定向(allow_redirects=False
    • 原始请求体通过 request.read() 读取并作为 body 发送
  5. 流式响应转发

    • 创建 web.StreamResponse,设置状态码与响应头
    • 准备响应(await self.retResponse.prepare()
    • 分块读取后端响应(每次最多 40960 字节),逐块写入客户端
    • 所有 chunk 传输完成后,输出调试日志
异常处理:
  • 未显式捕获异常,若发生网络错误会抛出异常,建议上层调用者使用 try-except 包裹。
日志输出:
DEBUG: proxyProcessor: data=%s  # 输出代理配置数据
DEBUG: proxy: datahandle() finish  # 表示代理完成

原代码问题修复:

  • paamsparams(拼写错误)
  • g.get('headers')d.get('headers')(应是 d 不是 g
  • regH.update(...)reqH.update(...)(变量名错误)

修正后关键片段:

if d.get('headers'):
    reqH.update(d['headers'])
params = None
if d.get('params'):
    params = d['params']  # 原代码为 params=params 错误

def setheaders(self)

占位方法,目前为空实现。

📌 作用:可能预留用于未来自定义响应头处理逻辑,当前无实际行为。


典型应用场景

  1. API 网关中的反向代理模块
  2. 内网服务暴露接口时的身份代理
  3. 动态路由 + 认证透传
  4. 前端请求经由后端代理避免 CORS

配置结构示例JSON 模板)

假设模板字符串为:

{
  "url": "https://external-api.com{{ path }}",
  "method": "{{ method | default('GET') }}",
  "user": "{{ username }}",
  "password": "{{ password }}",
  "headers": {
    "Authorization": "Bearer {{ token }}"
  },
  "params": {
    "limit": 100
  }
}

配合上下文变量(run_ns)即可动态生成请求配置。


已知问题与改进建议

问题 描述 建议
变量名拼写错误 paams, g.get, regH 修复为 params, d.get, reqH
缺少异常处理 网络请求失败可能导致服务崩溃 添加 try...except 并返回适当错误响应
无超时控制 client.request() 未设置超时 添加 timeout=aiohttp.ClientTimeout(...)
不支持 HTTPS 客户端验证配置 固定使用默认连接池 可扩展支持 SSLContext 或自定义 connector

示例配置调用流程

# 假设路由匹配触发 ProxyProcessor
request = web.Request(...)  # 来自客户端
processor = ProxyProcessor()
await processor.datahandle(request)
# 结果:流式转发远程服务响应给客户端

总结

ProxyProcessor 提供了一个灵活、可扩展的异步代理解决方案,支持模板驱动的请求配置,适用于现代微服务架构中的中间层代理需求。需注意修复现有代码中的拼写错误,并增加健壮性处理(如超时、异常兜底等)以提升生产可用性。


文档版本v1.0
📅 最后更新2025-04-05
© 项目组公共组件团队