ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

在 Homepage 中集成 UniFi Drive 存储状态 Widget:配置指南与源码级原理剖析

2026/9/10 12:00:24 拓冰建站 浏览量
在 Homepage 中集成 UniFi Drive 存储状态 Widget:配置指南与源码级原理剖析 在 Homepage 中集成 UniFi Drive 存储状态 Widget配置指南与源码级原理剖析【免费下载链接】homepageA highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.项目地址: https://gitcode.com/GitHub_Trending/ho/homepage本文围绕 Homepage 项目中的 UniFi Drive 服务 Widget 展开讲解如何通过一个本地 UniFi 账号将 UniFi 网络附加存储UNAS设备的容量与健康状态直接展示在你的起始页仪表盘上。读完本文你将掌握完整的 YAML 配置方法、四个可展示字段的取值含义以及从认证、API 调用到前端渲染的完整实现链路。UniFi Drive Widget 能做什么UniFi Drive 是 Homepage 提供的服务型 Widget 之一完整清单见 服务 Widget 索引专门用于展示 UniFi Network Attached StorageUNAS设备的存储统计信息。它不会展示文件列表或具体数据而是聚焦于存储池Storage Pool层面的关键指标存储池总容量Total已用空间Used可用空间Available存储池健康状态Status该 Widget 的官方文档位于 docs/widgets/services/unifi-drive.md其描述明确指出需要本地 UniFi 账号且该账号至少应具备读取权限read privileges。提示如果你需要的是 UniFi Network Controller而非 UNAS的连接状态展示请参阅 UniFi Controller Widget两者的类型标识、配置参数和 API 路径均不相同不要混用。前置条件在配置之前请确认以下前提是否满足你拥有一台 UniFi 网络附加存储UNAS设备并已将其接入你的网络。你拥有该设备的本地 UniFi 账号非仅限云端账号且该账号至少具备读取权限。Homepage 实例能够通过网络访问 UNAS 设备的地址url参数指向的地址。在 services.yaml 中配置 WidgetUniFi Drive Widget 的配置与 Homepage 其他服务 Widget 一样位于服务的widget字段中服务配置文件的骨架示例见 src/skeleton/services.yaml。完整的配置块如下widget: type: unifi_drive url: https://unifi.host.or.ip username: your_username password: your_password配置参数说明参数必填说明type是固定为unifi_drive用于告诉 Homepage 加载哪个 Widget 实现url是UNAS 设备的主机名或 IP 地址可包含https://协议头。注意 formatApiCall 会移除 URL 末尾多余的/斜杠因此无需担心尾斜杠问题username是本地 UniFi 账号的用户名password是对应用户名的密码在url中如非默认端口也可显式指定端口例如https://unifi.host.or.ip:8443。可选字段过滤与 Homepage 其他服务 Widget 一致UniFi Drive 支持通过fields过滤展示的指标块。官方文档明确给出的允许字段为[total, used, available, status]例如只展示容量与可用空间widget: type: unifi_drive url: https://unifi.host.or.ip username: your_username password: your_password fields: - total - available字段过滤由 Container 组件 实现它会依据service.widget.fields对子级Block进行匹配未命中字段的指标块会被隐藏。字段名若不含.会自动以 Widget 类型unifi_drive作为命名空间前缀进行匹配。前端展示逻辑四个指标块与状态映射前端组件实现位于 src/widgets/unifi_drive/component.jsx它定义了该 Widget 的展示行为加载占位数据未返回时渲染 4 个带骨架动画的占位块total/used/available/status。无数据兜底当 API 返回的pools不是数组或为空数组时仅显示一条 No storage data available中文环境为无可用存储数据对应 本地化文件 中的unifi_drive.no_data。多存储池聚合UNAS 可能包含多个存储池。组件会对所有池的容量与用量做累加totalBytes 所有池capacity之和usedBytes 所有池usage之和availableBytesmax(0, totalBytes - usedBytes)状态归一化任一池状态为degraded时整体显示降级若所有池均为fullyOperational或noDataProtectionYet尚未配置数据保护则整体显示正常healthy。状态值与展示文案的映射关系如下对应 英文本地化池状态API 原始值展示文案en展示文案zh-HansfullyOperationalHealthy正常noDataProtectionYetHealthy正常degradedDegraded已降级其他值原样透传原样透传容量数值通过t(common.bytes, { value })格式化为人类可读的字节单位该翻译 key 在 Homepage 多个资源类 Widget如 resources、glances中被复用。Block组件还支持基于高亮规则utils/highlights对指标值进行颜色标记实现代码见 src/components/services/widget/block.jsx。源码级原理认证与 API 调用链路UniFi Drive Widget 的底层实现分为三层理解它们有助于排查问题1. API 定义层widget.jssrc/widgets/unifi_drive/widget.js 定义了 Widget 的 API 模板与端点映射const widget { api: {url}{prefix}/api/{endpoint}, proxyHandler: unifiDriveProxyHandler, mappings: { storage: { endpoint: v2/storage, }, }, };API 模板为{url}{prefix}/api/{endpoint}其中{url}来自配置{prefix}由代理层动态解析{endpoint}由mappings.storage指定为v2/storage。前端通过useWidgetAPI(widget, storage)请求时最终会请求形如https://unifi.host.or.ip/proxy/drive/api/v2/storage的地址。2. 请求上下文解析层proxy.jssrc/widgets/unifi_drive/proxy.js 是 UniFi Drive 专属的代理入口通过getServiceWidget(group, service, index)从当前服务配置中取出 Widget 配置。首次请求时先对widget.url发起一次探测请求从响应头中提取x-csrf-token并将前缀/proxy/drivedrivePrefix写入内存缓存。前缀缓存 key 为unifiDriveProxyHandler__prefix.{service}后续请求直接复用避免重复探测这一点在 proxy.test.js 的 skips prefix detection when cached 测试用例中有明确验证。3. 通用 UniFi 代理层handlers/unifi.jssrc/utils/proxy/handlers/unifi.js 是一个可复用的 UniFi 认证代理工厂UniFi Drive 与 UniFi Controller 等 Widget 共用此实现。其关键流程为携带会话请求数据使用内存缓存的前缀构造 API URL并通过 cookie-jar 机制附加已保存的 Cookie。401 时自动登录当首次请求返回401会话失效或尚未登录且配置中无key时代理会向auth/login端点发起 POST 请求请求体为{ username, password, remember: true, rememberMe: true }并携带从响应头提取的x-csrf-token。登录成功判定解析登录响应若meta.rc ok或存在login_time/update_time字段则视为登录成功并将响应中的 Set-Cookie 存入 Cookie Jar。重放请求登录成功后使用新 Cookie 重新请求目标端点最终将 UNAS 返回的存储数据原样透传给前端。整个 HTTP 请求统一走 src/utils/proxy/http.js 的httpProxy它负责 Cookie 管理与重定向时的 Cookie 续写、gzip/deflate 响应解压以及 Alpine/musl 环境下的 DNS 解析兜底HOMEPAGE_PROXY_DISABLE_IPV6true可强制走 IPv4。该行为在 proxy.test.js 中有完整覆盖配置缺失返回 400、Widget 类型无 API 配置返回 403、正常路径返回 200 并缓存前缀等。常见问题与故障排查凭据错误导致 API Error官方文档特别提示如果输入了错误的凭据并收到 API Error你可能需要重新创建容器或重启服务以清除缓存。这与实现细节直接相关UniFi 代理层会将前缀/proxy/drive和 Cookie 写入内存缓存memory-cache。当凭据已变更但缓存中的会话 Cookie 仍有效或残留时代理不会触发重新登录导致反复出现认证错误。此时重启 Homepage 容器/服务以清空内存缓存即可恢复正常。登录返回非 200 或响应不含成功标志代理层会分别记录错误日志HTTP %d logging in to UniFi或Error logging in to UniFi并返回对应状态码。请检查username/password是否正确账号是否具备读取权限url是否能被 Homepage 容器正常访问网络互通、证书是否被信任——注意 http.js 中 https Agent 设置了rejectUnauthorized: false即不校验服务端证书便于连接自签名证书的 UNAS。显示 No storage data available当 API 正常返回但pools数组为空或缺失时会出现该提示。这可能意味着设备尚未创建任何存储池或当前账号无权查看存储池信息。延伸阅读其他 UniFi 系列 WidgetUniFi Controller 服务 Widget、UniFi Controller 信息 Widget全部服务 Widget 索引服务配置骨架参考src/skeleton/services.yaml实现源码widget.js、proxy.js、component.jsx、通用 UniFi 代理测试用例proxy.test.js、component.test.jsx【免费下载链接】homepageA highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.项目地址: https://gitcode.com/GitHub_Trending/ho/homepage创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考