API 图库
接入任意外部图片 API,定时拉取素材并在前台展示。图片只缓存地址等元数据,文件始终由第三方图源提供,不下载、不写入附件库,不占用一点本地存储。
应用市场填写信息
| 字段 | 值 |
|---|---|
| 应用名称 | API 图库 |
| 标识 | api-gallery |
| 版本 | 1.4.2 |
| Halo 版本要求 | >= 2.20.0 |
| 协议 | MIT |
| 开源 | 是(仓库 https://github.com/lu7875/halo-plugin-api-gallery) |
| 作者 | kbmp(https://github.com/lu7875) |
| 主页 | https://github.com/lu7875/halo-plugin-api-gallery |
| 源码仓库 | https://github.com/lu7875/halo-plugin-api-gallery |
| 问题反馈 | https://github.com/lu7875/halo-plugin-api-gallery/issues |
| 一句话简介 | 接入外部图片 API,在前台实时展示图库资源;图片不落本地存储,支持多数据源、定时同步与滚动更新 |
AI 使用声明:本项目在开发过程中使用了 AI 辅助编码(AI-substantial)。提交上架前已由开发者对权限边界、对外 HTTP 请求、诊断接口脱敏与上架材料做人工复查,并在 Halo 2.27.1 实机安装验证。1.4.1 / 1.4.2 针对审核意见,人工复测了图源 302/307 跳转目标逐跳校验(内网/回环/云元数据/非 http 协议均拒绝、合法跳转与相对路径正常跟随)、302 随机图源 Location 与随机 JSON 图片地址的二次校验、初始地址 SSRF 校验,以及随机源多轮定时同步的滚动更新与去重行为。
功能特性
- 零存储占用 — 只保存
{id, url, title, tags, source}元数据,图片由访客浏览器直连图源 CDN,不创建附件、不消耗磁盘 - 多数据源 — 后台可添加任意数量的图源,各自独立开关、独立统计张数与错误
- 三种响应结构自适应 — 自动识别顶层数组、
{items:[...]}包裹、单个对象(随机图接口);也可手动指定 - 支持 302 随机图源 — 没有列表接口、每次请求直接跳转到随机图的源(如 random-pictures 类站点),插件会重复采样并去重,攒成图集
- 定时同步 + 周期热更新 — 默认 60 分钟一轮(可调 5–1440 分钟),后台改完周期保存即刻生效,不用重启插件
- 滚动更新(1.3.0) — 随机类图源每轮同步都会换进一批新图并淘汰最老的,素材持续更新,不会攒满就静止
- 对接官方「图库管理」 — 可把图片地址写成
Photo记录,直接在后台/console/photos与主题/photos页面呈现,依然不占存储 - 前台展示页随包提供(1.4.0) — 瀑布流 + 懒加载 + 灯箱 + 按源筛选的展示页直接打进 jar,启用即可访问
- 访客可读 — 自动为匿名用户放行只读接口,前台页面无需登录即可展示(可关闭)
- 开箱即用 — 未配置时内置示例图源,装完启用就有图
安全设计(1.4.0 重点)
本插件会根据后台配置的地址向外部发起 HTTP 请求,因此做了三层边界:
| 层面 | 措施 |
|---|---|
| 对外请求 | 每次请求前执行 SSRF 校验:仅允许 http/https,拒绝回环、私有网段(10/8、172.16/12、192.168/16)、链路本地 169.254/16(含云元数据端点)、IPv6 唯一本地 fc00::/7、组播与广播;域名解析后的每个 IP 都要过网段检查 |
| 跳转防护(1.4.1) | 关闭自动跟随跳转,改为手动逐跳跟随;每一跳跳转前重新校验协议/主机/解析 IP,跳转目标必须同样是公网 http/https,限制最大 5 跳防重定向循环 |
| 响应地址校验(1.4.2) | 302 随机图源的 Location、200 兜底文本、随机单张 JSON 里的图片地址,先归一为绝对 URL 再执行同一套完整 SSRF 校验;不合法直接丢弃,不写入缓存、图库或前台页面 |
| 接口权限 | 接口拆成公开只读组(api.gallery.halo.run,可对访客放行的只有 /items、/random)与管理诊断组(console.gallery.halo.run,含 /sources、/diagnose、/sync、/push-to-photos、/photos,永不对匿名放行) |
| 诊断脱敏 | /diagnose 不返回响应正文、字段值、异常消息与堆栈;只回 httpStatus、contentType、bodyLength、looksLikeJson、rows / rowFields(仅字段名)与异常类名 |
| 写操作隔离 | 写入图库的记录统一带 api-gallery.kbmp.club/managed=true 标签,撤回时只删这一批,不动手工上传的照片 |
安装使用
- 下载
api-gallery-1.4.2.jar(GitHub Releases 或 Halo 应用市场) - 后台 → 插件 → 上传安装并启用
- 插件详情 → 设置 → 「API 数据源」添加图源,保存后约 1–3 秒完成首次同步
- 前台调用接口或打开随包的展示页即可看到图片
前台展示页(随 jar 提供)
启用插件后直接访问:
https://<你的站点>/plugins/api-gallery/assets/static/gallery.html
也可把它放进主题目录,或用 iframe 嵌入任意页面。该路径由插件内置的静态资源代理提供,
不是 /plugins/api-gallery/static/...。
添加图源
| 字段 | 示例 | 说明 |
|---|---|---|
| 名称 | 派次元 |
显示用,也是同步进图库时的分组名 |
| API 地址 | https://t.paiii.cn/api/random?format=json |
支持列表接口、随机图接口、302 跳转;必须是公网地址 |
| 响应结构 | 自动识别 / 随机单张 JSON / 302 跳转 | 不确定就选自动识别 |
| 采样次数 | 30 | 随机类图源每轮请求多少次(上限 200) |
| 最多累积 | 60 | 该源图池大小,达到后淘汰旧图(上限 5000) |
采样采用串行 + 120 ms 间隔,30 次约 3–8 秒,不会把免费图源打挂。
支持的图源类型
| 类型 | 典型地址 | 行为 |
|---|---|---|
| 固定列表 | https://t.paiii.cn/api/list |
每次返回内容一致,同步多少次都是同一批图 |
| 随机单张 JSON | https://t.paiii.cn/api/random?format=json |
每次返回不同图,采样累积成图集 |
| 302 跳转 | https://api.6045833.xyz/dongman |
读取跳转地址,重复采样去重后成图集 |
实测:/api/random?format=json 采样 12 次得 12 张不重复(约 2.9 秒),api.6045833.xyz 采样 12 次得 12 张不重复(约 3.4 秒)。
与「图库管理」插件的关系
两者定位不同,可配合使用:
- 图库管理(plugin-photos)负责存储与管理照片,提供
/photos路由与模板 - API 图库负责从外部图源取素材,不存储文件
开启「同步到图库管理」后,本插件会把图片地址写成 Photo 记录,于是后台 /console/photos 和主题 /photos 页面都能展示这些外链图,磁盘占用仍为零。写入的记录带 api-gallery.kbmp.club/managed=true 标签,撤回时只删这一批,不会动你手工上传的照片。
对外接口
公开只读组(可对访客放行)
基址:/apis/api.gallery.halo.run/v1alpha1
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /items?source=&page=1&size=20 |
分页返回图片元数据 |
| GET | /random?source= |
随机一张,适合做站点头图或背景 |
管理诊断组(需后台登录,不对匿名开放)
基址:/apis/console.gallery.halo.run/v1alpha1
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /sources |
各图源张数、上次/下次同步时间、错误原因 |
| GET | /diagnose |
逐个源实探一次,返回脱敏状态 |
| POST | /sync |
手动触发同步 |
| POST | /push-to-photos |
手动推送到图库 |
| DELETE | /photos |
撤回本插件写入图库的记录 |
1.3.1 及以前这些管理接口位于
api.gallery.halo.run组,1.4.0 起迁到console.gallery.halo.run。
注意事项
- 依赖第三方图源:图源挂了前端就加载不出图,已同步的元数据仍在,图源恢复后自动可用
- 缓存是进程内的:重启 Halo 后缓存清空,启动后会自动重新同步,无需人工干预
- 图源需开放跨域:图片由访客浏览器直连图源,图源未开放 CORS 时前端会加载失败
- 图源必须是公网地址:内网/回环地址会被 SSRF 防护主动拒绝(安全策略,非缺陷)
- 同步周期不宜过短:建议不低于 5 分钟,太频繁可能被图源限流
- 版权:图片版权归各图源及其投稿者,商用前请自行确认授权
常见问题
Q:设置了自动同步,图片却一直没变?
先看 /sources 接口:intervalMinutes 是当前实际生效的周期,lastSync/nextSyncAt 是上次/下次同步时间,secondsUntilNextSync 为 -1 说明周期任务没排上。
两种典型情况:
- 周期没生效 — 1.2.0 起保存设置会立即按新周期重新排期,无需重启
- 同步了但内容本就不变 — 固定列表类图源每次返回完全相同的内容,同步一万次也是同一批图。想要素材有变化,请改用随机类图源
Q:前台请求 /items 返回 302?
公开只读组未对访客放行。确认「同步设置 → 允许访客查看图库」已开启并保存;若自动授权失败,到后台 → 用户 → 角色 → 匿名角色手动勾选相关权限。
Q:同步后图源报错,提示 URL 协议或地址被拦?
这是 SSRF 防护生效了。图源必须是可从公网访问的 http/https 地址;内网、回环、云元数据地址一律拒绝。
Q:同步后图源报错?
看 /sources 里该源的 error 字段,常见原因是地址不通、返回非 JSON(例如随机图接口漏了 ?format=json,会返回图片二进制),或响应结构与所选解析方式不匹配。
Q:gallery.html 访问 404?
请访问 /plugins/api-gallery/assets/static/gallery.html(注意有 assets/static),
不是 /plugins/api-gallery/static/gallery.html。

