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

7.5 KiB
Raw Permalink Blame History

以下是为提供的 FunctionProcessor 类编写的 Markdown 格式技术文档,适用于项目开发文档或 API 文档场景。


FunctionProcessor 技术文档

概述

FunctionProcessor 是一个基于 aiohttp 的异步请求处理器类,继承自 BaseProcessor。它用于将 HTTP 请求动态映射到通过 RegisterFunction 注册的函数上,并支持路径参数解析和运行时环境注入。该处理器特别适用于实现基于注册函数的路由分发机制。

主要功能包括:

  • 解析 URL 路径中的参数
  • 调用已注册的同步或异步函数
  • 支持运行时命名空间(run_ns)注入上下文变量
  • 返回 ResponseFileResponse 或普通内容数据

导入依赖

import inspect
from appPublic.dictObject import DictObject
from appPublic.registerfunction import RegisterFunction
from appPublic.log import info, debug, warning, error, exception, critical
from aiohttp import web
from aiohttp.web_response import Response, StreamResponse
from .baseProcessor import BaseProcessor

依赖说明

模块 用途
inspect 判断目标函数是否为协程函数
DictObject 将字典转换为属性可访问的对象
RegisterFunction 获取全局注册的函数
appPublic.log 日志输出
aiohttp.web Web 服务核心组件
BaseProcessor 基础处理器基类

类定义

class FunctionProcessor(BaseProcessor):

继承自 BaseProcessor,用于处理特定类型的 HTTP 请求并调用注册函数。


类方法

isMe(name)

@classmethod
def isMe(cls, name):
    return False

说明

此方法用于判断当前处理器是否适用于给定名称的资源。在本实现中始终返回 False,表示此类不会自动匹配任何资源名 —— 其使用需显式配置。

⚠️ 注意:若需启用自动识别,请重写此方法以根据条件返回 True

参数

  • name (str) - 资源名称

返回值

  • bool: 始终返回 False

实例方法

__init__(path, resource, opts)

构造函数,初始化处理器实例。

def __init__(self, path, resource, opts):
    self.config_opts = opts
    BaseProcessor.__init__(self, path, resource)

参数

参数 类型 说明
path str 请求路径模板
resource Any 关联资源对象(未具体使用)
opts dict 配置选项,必须包含以下键:
leading: 前缀路径,用于截断
registerfunction: 注册函数名

属性设置

  • self.config_opts: 存储传入的配置项
  • 调用父类初始化逻辑

path_call(request, params={})

执行注册函数的核心方法,负责解析路径、获取函数并调用。

async def path_call(self, request, params={}):

流程说明

  1. 设置运行时环境(通过 set_run_env
  2. 提取 params_kw 和实际请求路径
  3. 截去配置中指定的前缀(leading),拆分剩余路径作为位置参数
  4. RegisterFunction 中获取目标函数
  5. 若函数未注册,记录错误日志并返回 None
  6. 构造调用环境(排除敏感键)
  7. 异步或同步调用函数并返回结果

参数

参数 类型 说明
request aiohttp.web.Request 当前 HTTP 请求对象
params dict 可选参数字典,可覆盖默认路径等信息

返回值

  • 函数调用结果(可以是 Response, str, dict, 或其他类型)
  • 如果函数未注册,返回 None

内部逻辑细节

路径处理
path1 = path[len(self.config_opts['leading']):]
if path1[0] == '/': path1 = path1[1:]
args = path1.split('/')

例如:
request.path = "/api/v1/user/123",且 leading="/api/v1",则 args = ['user', '123']

函数调用环境构建
env = {k:v for k,v in self.run_ns.items() if k not in ['params_kw', 'request']}

过滤掉 params_kwrequest,避免重复传参冲突。

协程支持
if inspect.iscoroutinefunction(f):
    return await f(request, params_kw, *args, **env)
return f(request, params_kw, *args, **env)

自动识别函数类型,确保正确调用同步或异步函数。

错误处理
if f is None:
    error(f'{rfname=} is not registered, {rf.registKW=}')
    return None

若函数未注册,输出调试信息并返回 None


datahandle(request)

处理请求并生成响应内容的方法。

async def datahandle(self, request):
    x = await self.path_call(request)
    if isinstance(x, web.FileResponse):
        self.retResponse = x
    elif isinstance(x, Response):
        self.retResponse = x
    else:
        self.content = x

功能

调用 path_call 执行业务逻辑,并根据返回值类型决定如何封装响应:

返回类型 处理方式
web.FileResponse 直接赋值给 self.retResponse
Response(含子类) 赋值给 self.retResponse
其他类型(如 str, dict 等) 赋值给 self.content,由后续中间件或父类序列化

参数

  • request: aiohttp.web.Request 对象

影响属性

  • self.retResponse: 成功时保存响应对象
  • self.content: 成功时保存原始内容数据

配置要求(opts

FunctionProcessor 必须接收如下配置项:

键名 类型 说明
leading str 需要从路径中去除的前缀,如 /api/v1
registerfunction str RegisterFunction 中注册的函数名称

示例配置:

opts = {
    "leading": "/api/v1",
    "registerfunction": "my_registered_handler"
}

使用示例

注册函数示例

from appPublic.registerfunction import RegisterFunction

def my_handler(request, params, *args, **env):
    return web.json_response({"args": args, "env": env})

RegisterFunction().register("my_registered_handler", my_handler)

创建处理器并处理请求

processor = FunctionProcessor("/api/v1/data/*", None, {
    "leading": "/api/v1/data",
    "registerfunction": "my_registered_handler"
})

# 在 aiohttp 路由中调用
async def handle_request(request):
    await processor.datahandle(request)
    if processor.retResponse:
        return processor.retResponse
    return web.json_response(processor.content)

注意事项与限制

  1. 函数注册必需:目标函数必须提前通过 RegisterFunction().register(name, func) 注册。
  2. 函数签名要求:被调用函数应接受 (request, params_kw, *args, **kwargs) 形式的参数。
  3. 路径前缀必须匹配leading 必须准确匹配请求路径开头,否则可能导致参数解析异常。
  4. 非标准返回值需手动处理:若返回非 Response 类型,需确保上游能正确序列化 self.content

日志输出

该类使用 appPublic.log 模块进行日志记录:

  • error: 函数未注册时输出详细错误信息
  • (其他日志级别暂未使用)

建议开启调试日志以便追踪调用过程。


总结

FunctionProcessor 提供了一种灵活的函数驱动式 Web 接口设计模式,适合微服务、插件化系统或需要动态绑定逻辑的场景。结合 RegisterFunction 机制,实现了低耦合、高扩展性的请求处理架构。


文档版本1.0
📅 最后更新2025-04-05