尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Ajenti 插件开发指南:通过 HttpPlugin 与 @endpoint 构建 HTTP 处理接口

发布时间:2026/9/26 15:56:24

资讯中心
01
ARTICLE

Ajenti 插件开发指南:通过 HttpPlugin 与 @endpoint 构建 HTTP 处理接口

Ajenti 插件开发指南:通过 HttpPlugin 与 @endpoint 构建 HTTP 处理接口
后端运维【免费下载链接】ajentiAjenti Core and stock plugins项目地址https://gitcode.com/gh_mirrors/aj/ajenti点击查看免费下载导读本文围绕 docs/source/dev/http.rst 的开发者文档展开系统讲解 Ajenti 插件如何注册并处理 HTTP 请求从继承HttpPlugin抽象接口、使用get/post等路由装饰器到用endpoint开启 JSON API 模式或底层页面模式再到HttpContext提供的完整响应控制能力。读完本文你将能够为 Ajenti 编写出可被前端直接调用的 REST 风格 API 端点并理解请求从 WSGI 进入后经 master/worker 架构最终派发到插件处理器的完整链路。一、Ajenti 的 HTTP 请求处理架构概览Ajenti 采用 master/worker 的多进程架构主进程master负责会话管理与请求接收每个登录会话由独立的 worker 子进程承载参见 aj/gate/gate.py 中WorkerGate对 gipc 管道与子进程的封装。一次 HTTP 请求的生命周期大致如下WSGI 请求进入HttpRoot被包装为HttpContextaj/http.pyGateMiddleware依据 Cookie 会话或 HTTP Basic 认证找到或新建对应 worker将序列化后的HttpContext通过管道发送过去aj/gate/middleware.pyworker 进程内的Worker.handle_http_request反序列化上下文交给AuthenticationMiddleware与CentralDispatcher组成的中件栈aj/gate/worker.pyCentralDispatcher遍历所有已注册的HttpPlugin实例命中路由则执行对应处理函数并返回结果aj/routing.py。因此插件的 HTTP 能力本质上就是向HttpPlugin这一接口注册组件。理解这条链路有助于定位为什么我的端点没被调用之类的问题路由匹配、方法匹配与认证检查都发生在 worker 进程内。二、定义 HTTP 端点HttpPlugin 接口与路由装饰器2.1 继承 HttpPlugin插件通过扩展aj.api.http.HttpPlugin抽象类来提供自己的 HTTP 端点并用jadi的component机制注册例如from jadi import component from aj.api.http import get, HttpPlugin component(HttpPlugin) class Handler(HttpPlugin): def __init__(self, context): self.context context get(r/api/demo4/calculate/(?Poperation\w)/(?Pa\d)/(?Pb\d)) def handle_api_calculate(self, http_context, operationNone, aNone, bNone): http_context.respond_ok() return Hello!HttpPlugin在 aj/api/http.py 中定义其handle(http_context)方法会遍历类字典中带有url_pattern属性的方法用编译后的正则匹配http_context.path命中后将命名捕获组作为关键字参数传入处理函数。__init__(self, context)中保存的context携带身份信息context.identity、worker 引用等运行时数据。2.2 请求方法装饰器get、post、delete、head、put、patchaj.api.http通过requests_decorator_generator动态生成了完整的 HTTP 方法装饰器aj/api/http.py标准 HTTP 方法get、post、delete、head、put、patchWebDAV 方法propfind、mkcol、options、proppatch、copy、move、lock、unlockAjenti 的文件管理、WebDAV 相关功能即依赖这些方法。用法统一为get(r/api/foo/(?Pid\d)) def handle_foo(self, http_context, idNone): ...装饰器接收一个 URL 正则pattern^与$是隐式添加的即整个路径必须完全匹配参见 aj/api/http.py 中re.compile(f^{pattern}$)。正则中的命名捕获组(?Pname...)会在匹配后作为**kwargs注入处理函数。方法匹配由HttpPlugin.handle内部的check_method完成aj/api/http.py规则如下处理函数标注的 method 与http_context.method取自REQUEST_METHOD统一转为大写一致才可调用HEAD 请求被允许打在 GET 目标上以兼容健康检查等场景处理函数返回值若为str会被编码为 UTF-8 字节若为生成器types.GeneratorType如流式文件下载则原样透传aj/api/http.py。2.3 旧式 url 装饰器的兼容代码库中还存在较早的url(pattern)装饰器aj/api/http.py它只绑定url_pattern而不绑定 method。HttpPlugin.handle在检测到方法上没有method属性时会回退到旧式兼容路径并输出日志警告Backward url compatibility ...。新代码应一律使用get/post等按方法区分的装饰器。三、endpointAPI 模式与页面模式原文档强调建议给所有 HTTP 处理方法都加上endpoint装饰器。endpoint(pageFalse, apiFalse, authTrue)定义在 aj/api/endpoint.py三个参数含义如下参数默认值作用authTrue要求已认证会话否则返回401 UnauthenticatedapiFalse将响应与异常自动包装为 JSON并特殊处理EndpointErrorpageFalse启用页面模式提供对 HTTP 响应的底层控制3.1 endpoint(apiTrue)自动 JSON 编码import time from jadi import component from aj.api.http import get, HttpPlugin from aj.api.endpoint import endpoint, EndpointError, EndpointReturn component(HttpPlugin) class Handler(HttpPlugin): def __init__(self, context): self.context context get(r/api/demo4/calculate/(?Poperation\w)/(?Pa\d)/(?Pb\d)) endpoint(apiTrue) def handle_api_calculate(self, http_context, operationNone, aNone, bNone): start_time time.time() try: if operation add: result int(a) int(b) elif operation divide: result int(a) / int(b) else: raise EndpointReturn(404) except ZeroDivisionError: raise EndpointError(Division by zero) return { value: result, time: time.time() - start_time }这是原文档给出的完整示例。在apiTrue模式下aj/api/endpoint.py处理函数的返回值dict、list 等会经simplejson.dumps序列化为 JSON自动写入Content-Type: application/json响应头异常按类型转换为对应 HTTP 状态码与 JSON 错误体详见下文第四节。3.2 endpoint(pageTrue)底层响应控制当你需要完全控制响应头、返回非 JSON 内容如 HTML、XML、文件流时使用pageTrueget(r/api/test) endpoint(pageTrue) def handle_api_calculate(self, http_context): http_context.add_header(Content-Type, ...) content Hello! # return http_context.respond_not_found() # return http_context.respond_forbidden() # return http_context.file(/some/path) http_context.respond_ok() return content在页面模式下endpoint不会自动序列化返回值也不会把异常转成 JSONEndpointError、SecurityError与其他异常都会直接向上抛出aj/api/endpoint.py由CentralDispatcher捕获并渲染错误页。处理函数负责自己调用http_context的响应方法见第五节。注意endpoint是包裹在路由装饰器外层的装饰顺序为上例所示即先get标记路由再endpoint包装执行逻辑二者缺一不可。四、异常与状态码的约定EndpointError、EndpointReturn、SecurityErrorendpoint的异常处理逻辑定义了 Ajenti API 的错误语义aj/api/endpoint.pyEndpointReturn(code)主动返回指定 HTTP 状态码可在响应体中附带data。例如上述计算 API 中对未知操作raise EndpointReturn(404)。它的语义是可预见的业务性返回不会触发客户端崩溃对话框EndpointError(message)表示可预见的错误如除零、参数非法。在apiTrue模式下转为500状态码并返回包含message、exception类名与traceback的 JSON 对象aj/api/endpoint.pySecurityError权限不足时抛出apiTrue模式下转为403 Forbiddenaj/api/endpoint.py。SecurityError定义于 aj/auth.py其 message 形如Forbidden: permission ... is required未捕获的普通异常在apiTrue模式下同样转为500并返回带 traceback 的 JSON便于前端排查在pageTrue模式下则重新抛出交给上层。另外若处理函数内部已通过http_context.respond(404 Not Found)等方式设置过状态endpoint会检测context.status中不含200的情况并加以传播aj/api/endpoint.py。五、HttpContext请求数据与响应控制每个处理函数接收的第一个参数都是HttpContext实例aj/http.py。它的主要属性包括属性说明envWSGI 环境字典pathURL 路径段method请求方法大写headers响应头列表键值对元组body请求体字节串query合并后的查询参数与表单参数response_ready是否已提交过响应5.1 读取请求数据查询字符串与表单HttpContext.__init__会同时解析 URL 查询串cgi.FieldStorage与application/x-www-form-urlencoded、multipart/form-data表单体CGIFieldStorage合并到query字典中aj/http.pyJSON 请求体http_context.json_body()直接对self.body做 UTF-8 解码与json.loadsaj/http.py。plugins/check_certificates/views.py 中的真实插件就是通过http_context.json_body()[url]读取 POST 载荷的。5.2 响应方法速查原文档提示参见aj.http.HttpContext获取可用的http_context方法以下是从 aj/http.py 提取的完整响应工具集方法效果respond(status)以任意状态行创建响应response_ready Truerespond_ok()200 OKrespond_server_error()500 Server Error返回[bServer Error]respond_unauthenticated()401 Unauthenticatedrespond_forbidden()403 Forbiddenrespond_not_found()404 Not Foundrespond_bad_request()400 Bad Requestredirect(location)302 Found并写入Location头add_header(key, value)追加响应头remove_header(key)移除指定响应头gzip(content, compression6)返回 gzip 压缩响应自动设置Content-Encoding与Content-Lengthfile(path, streamFalse, inlineFalse, nameNone)返回文件内容响应见 5.3run_response()最终调用 WSGIstart_response()补齐X-Frame-Options: SAMEORIGIN与 CSP 安全头5.3 file()内置的静态文件服务HttpContext.file()是页面模式下最实用的方法之一它已经处理了完整 HTTP 语义aj/http.py路径穿越防护路径含..直接返回 403MIME 类型映射.html、.css、.js、.png、.jpg、.svg、.woff、.pdf均有对应Content-Type其余回落为application/octet-stream条件请求支持If-Modified-Since返回304 Not Modified支持Range返回206 Partial Content下载语义inlineTrue时为内联展示否则为attachment下载并支持自定义filename流式读取streamTrue时以 100 KB 缓冲块配合gevent.sleep(0)让步逐块产出适合大文件。六、从源码看真实插件的 HTTP 端点写法6.1 证书检查插件post JSON 请求体plugins/check_certificates/views.py 展示了 POST 端点的标准范式component(HttpPlugin) class Handler(HttpPlugin): def __init__(self, context): self.context context post(r/api/check_cert) endpoint(apiTrue) def handle_api_check_cert(self, http_context): url http_context.json_body()[url] return json.loads(json.dumps(checkOnDom(*url.split(:))))6.2 Augeas 插件URL 参数 EndpointReturnplugins/augeas/views.py 演示了命名捕获组与业务性 404 的组合get(r/api/augeas/endpoint/(?Pid.)) endpoint(apiTrue) def handle_api_get(self, http_context, idNone): ep self.__get_augeas_endpoint(id) if not ep: raise EndpointReturn(404) aug ep.get_augeas() ...此外plugins/core/views/api.py 中集中体现了完整的方法矩阵get(/api/core/identity)、post(/api/core/auth)、delete(/api/core/totps/(?Ptimestamp\d*))等可作为编写 CRUD 风格端点的参考范本。七、请求处理流程与路由解析的源码级印证理解以下细节有助于调试端点不生效的问题Worker 内建处理器栈Worker.__init__构建了HttpMiddlewareAggregator([AuthenticationMiddleware, CentralDispatcher])aj/gate/worker.py并在每个请求到来时再叠加所有HttpMiddleware组件aj/gate/worker.py认证检查AuthenticationMiddleware.handle会处理 SSL 客户端证书并写入X-Auth-Identity头aj/auth.pyendpoint(authTrue)默认在context.identity为空时直接返回 401中央派发CentralDispatcher.handle遍历HttpPlugin.all(self.context)的所有实例依次调用instance.handle(http_context)谁返回非None输出就用谁的结果全部未命中则落入InvalidRouteHandler渲染 404 页面aj/routing.py。路由的^...$全匹配语义也意味着若你的正则写成了不带锚点的前缀匹配路径就不会命中worker 超时master 等待 worker 响应的默认超时为 600 秒超时返回504 Gateway Timeoutaj/gate/middleware.py因此长时间运行的任务不应阻塞在 HTTP 处理函数内。结语Ajenti 的 HTTP 处理模型非常简洁HttpPlugin负责把类方法映射为URL 路由endpoint负责把普通函数升级为带认证、带 JSON 编码、带错误约定的标准端点HttpContext则提供了构建任意响应文件、压缩流、重定向、自定义状态码的全部底层能力。掌握这三层抽象再对照 plugins/core/views/api.py 等仓库内真实插件的写法即可为 Ajenti 快速添加稳定的 API 端点。赞分享后端运维【免费下载链接】ajentiAjenti Core and stock plugins项目地址https://gitcode.com/gh_mirrors/aj/ajenti点击查看免费下载相关推荐Ajenti插件开发入门指南从零开始构建你的第一个管理面板插件Ajenti插件开发入门指南从零开始构建你的第一个管理面板插件 前言 Ajenti是一个功能强大的服务器管理面板框架它允许开发者通过插件扩展其功能。本文将带后端运维Envoy HTTP Cache Filter 存储插件开发指南深入理解 HttpCache、LookupContext 与 InsertContext 接口Envoy HTTP Cache Filter 存储插件开发指南深入理解 HttpCache、LookupContext 与 InsertContext 接口云原生服务网格网络微服务Telegraf ifname 处理器插件实战通过 SNMP 将接口编号解析为接口名称Telegraf ifname 处理器插件实战通过 SNMP 将接口编号解析为接口名称 导读 ifname 是 Telegraf 内置的流式处理器Strea可观测性指标监控运维创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。