开发与调试
本页汇总了编写插件时有用的工具:开发者模式下的测试实例、浏览器包的开发加载方式、日志、检查工具和一致性测试。
开发者模式
注意
在开发者模式之外,Nginx UI 只安装已签名的插件包。开发期间,请在测试实例(切勿在生产实例)上开启 偏好设置 > 插件 > 开发者模式。开发者模式会:
- 允许从上传、命令行或离线插件包目录安装未签名的插件包;
- 在 插件 页面显示开发工具。
它永远不会接受签名已损坏的插件包,也不会让未签名的插件参与自动更新。参见签名与信任。
快速重装
服务端进程的每次修改都需要一个新的插件包。有两种方法可以缩短这个循环:
- 在服务器上先运行
nginx-ui plugin pack <目录> <插件包>,再运行nginx-ui plugin install <插件包> --enable --approve-permissions,一步替换已安装的版本。 - 把插件包放进插件目录下的
packages目录(默认是<配置目录>/plugins/packages),Nginx UI 下次启动时如果发现它的版本比已安装的新,就会安装它,然后把它移到packages/installed。
发行版也可以把插件包放在一个只读目录里,用 [plugin] 段的 BundledDir 或环境变量 NGINX_UI_PLUGIN_BUNDLED_DIR 指定。官方 Docker 镜像就是这样内置 DNS-01 插件的。Nginx UI 会把每个内置插件安装并启用一次;内置的插件包版本更新时会升级它;用户卸载后不会再自动装回来。只有用官方插件密钥签名的插件包会从这个目录安装。
开发浏览器包
浏览器包可以从本地开发服务器加载,而不是从已安装的插件包加载,这样重新构建后只需刷新页面:
- 在运行浏览器的机器上用开发服务器提供插件目录(包括
plugin.json),例如vite build --watch加一个静态文件服务器。 - 在 插件 页面打开标签页旁的菜单,选择开发插件地址,输入
plugin.json的地址,例如http://localhost:5173/plugin.json。 - 刷新页面。
Nginx UI 会相对于该地址加载清单中指定的浏览器包、样式表和页面。由于页面每次访问都会执行这个脚本,只接受 localhost 地址。清空地址即可回到已安装的版本。
浏览器包一页介绍了如何构建浏览器包。
日志
注意
插件把自己的日志写到标准错误。Nginx UI 会捕获这些输出,并在 插件 页面的插件详情中显示。标准输出只能用于协议消息,写入任何其他内容都会破坏连接。SDK 会自动把日志输出到标准错误。
插件还可以通过 host.log 方法发送结构化日志,参见宿主 API。绝不要记录凭据或令牌,参见权限与安全。
检查插件
静态检查
nginx-ui plugin lint <插件目录或插件包>检查工具读取插件的清单和文件,一次性报告所有问题:清单字段、插件包的结构与限制、签名、能力块、模板和翻译文件。每个问题都有级别(error 或 warning)和规则名称,检查规则解释了每一条规则。
有错误的插件包无法安装。警告也应修复:它们指出的问题会被安装插件的人看到。
一致性测试
nginx-ui plugin conformance <插件目录或插件包> [参数]一致性测试使用 Nginx UI 自己的进程管理器和宿主 API 启动插件,检查它的行为:握手、健康检查、错误码、并发调用、关闭,以及它声明的每个能力的调用。测试绝不会调用会访问真实服务商或修改真实数据的方法:例如对 DNS-01 插件只会要求它校验一个空配置,而不会发布记录。
| 参数 | 含义 |
|---|---|
--capability | 只测试某一个能力,例如 dns01。 |
--transport | stdio、grpc 或 both。插件提供 gRPC 时默认为 both,否则为 stdio。 |
--timeout | 整个测试的时间上限,默认为 90s。 |
提供 gRPC 的插件会在两种传输方式上分别测试,且结果必须一致。没有服务端进程的插件只进行静态检查。
协议样例
plugin-spec 仓库的 vectors/v1 目录为每个方法提供了请求与响应样例。不使用 SDK 编写插件时,可以在单元测试中使用它们。Go SDK 的 sdk.Run 和 Rust SDK 的 run 可以通过内存管道驱动插件,用途相同。
常见问题
| 现象 | 原因 |
|---|---|
| 插件启动后立即失败。 | 握手前向标准输出写入了内容,或缺少当前平台的可执行文件。请查看插件日志。 |
| 握手因能力不匹配而失败。 | 进程报告的能力与清单中的 capabilities 不一致。 |
| 进程每隔几秒就被重启。 | 忙碌时没有响应 plugin.ping。应独立于耗时调用处理健康检查,参见生命周期。 |
| 宿主调用返回权限错误。 | 清单没有请求该权限,或者用户尚未批准。 |
| 浏览器包没有加载。 | 它没有用清单 ID 调用 registerPlugin,或者打包了自己的 Vue。参见浏览器包。 |