328 lines
11 KiB
Markdown
328 lines
11 KiB
Markdown
# PAR Server 接口升级对比文档 (供 MediaBot 迁移)
|
||
|
||
> **版本**: V2.0(SiteSnapshot 重构)
|
||
> **日期**: 2026-07-07
|
||
> **面向对象**: MediaBot 开发团队
|
||
|
||
---
|
||
|
||
## 一、升级概览
|
||
|
||
本次重构将站点配置的存储和分发方式从 **"分散存储 + 运行时合并"** 升级为 **"统一快照 + 增量更新"**。核心变化:
|
||
|
||
| 维度 | 旧方案 (V1) | 新方案 (V2) |
|
||
|------|------------|------------|
|
||
| **存储** | 脚本/页面/规则分别存七牛云 | MySQL `site_snapshots` 表统一存储 + 七牛云 CDN 灾备 |
|
||
| **获取方式** | 多次请求分别获取脚本、页面、规则 | **一次请求获取完整 bundle** |
|
||
| **更新检测** | 无/各接口各自判断 | **统一 checksum + ETag/304** 增量更新 |
|
||
| **可用性** | 依赖七牛云 | 数据库为主 + 七牛云 CDN 自动灾备 |
|
||
|
||
---
|
||
|
||
## 二、新增接口(推荐 MediaBot 迁移到这些)
|
||
|
||
### 2.1 `GET /api/v1/snapshots/{siteId}` ⭐ 推荐
|
||
|
||
**用途**: 获取站点完整配置快照(一站式获取脚本 + 页面配置 + 风险规则)
|
||
|
||
**查询参数**:
|
||
|
||
| 参数 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `preview` | boolean | `false` | `false`=仅正式版(published),`true`=预览版优先(draft → published fallback) |
|
||
|
||
**请求头**:
|
||
```
|
||
If-None-Match: {上次返回的 ETag checksum}
|
||
```
|
||
|
||
**响应 200 OK**(内容未变化时):
|
||
```json
|
||
{
|
||
"siteId": "example.com",
|
||
"generatedAt": "2026-07-07T10:30:00",
|
||
"script": "// Groovy 脚本完整源码...",
|
||
"scriptVersion": "3",
|
||
"scriptSource": "custom",
|
||
"pages": [
|
||
{
|
||
"pageKey": "INDEX",
|
||
"url": "https://example.com/torrents.php",
|
||
"method": "GET",
|
||
"...": "..."
|
||
}
|
||
],
|
||
"pagesVersion": "2",
|
||
"pagesSource": "custom",
|
||
"riskRules": [
|
||
{
|
||
"field": "title",
|
||
"operator": "contains",
|
||
"value": "xxx",
|
||
"level": "WARN"
|
||
}
|
||
],
|
||
"riskRulesVersion": 1
|
||
}
|
||
```
|
||
|
||
**响应 304 Not Modified**(内容未变化):
|
||
```
|
||
HTTP/1.1 304 Not Modified
|
||
ETag: "abc123def456..."
|
||
```
|
||
_(Body 为空,节省带宽)_
|
||
|
||
**可用性保障**(PAR Server 端三层级联):
|
||
- 第一层:优先从 MySQL 数据库读取
|
||
- 第二层:数据库异常时自动回退到七牛云 CDN `snapshots/{siteId}.json`
|
||
- 第三层:CDN 也无数据时,实时构建(从各子表 + 七牛云存储拼装)
|
||
- 全部失败返回 500
|
||
|
||
**MediaBot 端建议**(应对 PAR Server 整体不可用):
|
||
- MediaBot 应缓存每个站点的 CDN URL(`https://{七牛云CDN域名}/snapshots/{siteId}.json`)
|
||
- 当 PAR Server 连接超时/拒绝连接时,直接请求 CDN URL 作为终极 fallback
|
||
- 这样即使 PAR Server 宕机,配置仍可通过 CDN 获取(每次 publish 都会同步上传到 CDN)
|
||
|
||
---
|
||
|
||
### 2.2 `GET /api/v1/snapshots/{siteId}/check` ⭐ 推荐
|
||
|
||
**用途**: 轻量级检查站点是否有配置更新(不传输配置内容)
|
||
|
||
**响应**:
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"data": {
|
||
"checksum": "abc123def456...",
|
||
"version": 5,
|
||
"publishedAt": "2026-07-07T10:30:00"
|
||
}
|
||
}
|
||
```
|
||
|
||
**使用模式**:
|
||
1. MediaBot 先调 `/check` 获取最新 `checksum`
|
||
2. 与本地缓存的 checksum 比较
|
||
3. 不同时再调 `/snapshots/{siteId}` 拉取完整配置
|
||
|
||
---
|
||
|
||
## 三、旧接口兼容状态
|
||
|
||
以下接口**继续可用**,但推荐逐步迁移到新接口:
|
||
|
||
### 3.1 `GET /api/v1/configs/{siteId}/bundle` — ⚠️ 保持兼容
|
||
|
||
| 项目 | 说明 |
|
||
|------|------|
|
||
| **状态** | 继续可用,底层已委托给快照服务 |
|
||
| **变化** | 无破坏性变化,响应格式不变 |
|
||
| **建议** | 可继续使用,但建议迁移到 `GET /api/v1/snapshots/{siteId}` |
|
||
|
||
**数据流变化**:
|
||
```
|
||
旧: 七牛云 bundles/{siteId}.json → 返回
|
||
新: MySQL site_snapshots → 返回 (优先)
|
||
↓ 失败
|
||
七牛云 bundles/{siteId}.json / snapshots/{siteId}.json → 返回 (回退)
|
||
↓ 失败
|
||
实时构建 → 返回 (兜底)
|
||
```
|
||
|
||
### 3.2 `GET /api/v1/configs/{siteId}/script` — ⚠️ 保持兼容
|
||
|
||
| 项目 | 说明 |
|
||
|------|------|
|
||
| **状态** | 无变化,功能一致 |
|
||
| **建议** | 如需单独获取脚本,可继续使用;否则建议用 snapshot 一次性获取 |
|
||
|
||
### 3.3 `GET /api/v1/scripts/{siteId}` — ⚠️ 保持兼容
|
||
|
||
| 项目 | 说明 |
|
||
|------|------|
|
||
| **状态** | 无变化,功能一致 |
|
||
| **说明** | 仅返回 Groovy 脚本纯文本,无 JSON 包装 |
|
||
| **建议** | 如需单独获取脚本,可继续使用 |
|
||
|
||
### 3.4 `GET /api/v1/scripts/{siteId}/version` — ⚠️ 保持兼容
|
||
|
||
| 项目 | 说明 |
|
||
|------|------|
|
||
| **状态** | 无变化 |
|
||
| **响应** | `{ "version": "3", "source": "custom" }` |
|
||
| **建议** | 可用 `/snapshots/{siteId}/check` 替代,后者提供更全面的版本信息 |
|
||
|
||
### 3.5 `GET /api/v1/manifest` — ⚠️ 保持兼容
|
||
|
||
| 项目 | 说明 |
|
||
|------|------|
|
||
| **状态** | 无变化,仍支持 ETag |
|
||
| **说明** | 返回所有活跃站点配置索引(siteId、站点类型、是否有脚本/页面/规则等元信息) |
|
||
| **建议** | 继续用于获取全量站点列表和配置状态概览 |
|
||
|
||
### 3.6 `GET /api/v1/sites/{siteId}/pages` — ⚠️ 保持兼容
|
||
|
||
| 项目 | 说明 |
|
||
|------|------|
|
||
| **状态** | 无变化 |
|
||
| **建议** | 如只需页面配置,可继续使用;否则建议用 snapshot |
|
||
|
||
### 3.7 `GET /api/v1/risk-rules/{siteType}` — ⚠️ 保持兼容
|
||
|
||
| 项目 | 说明 |
|
||
|------|------|
|
||
| **状态** | 无变化,仍支持版本号增量判断 |
|
||
| **建议** | 如只需风险规则,可继续使用;否则建议用 snapshot |
|
||
|
||
---
|
||
|
||
## 四、推荐 MediaBot 迁移方案
|
||
|
||
### 方案 A:完全迁移到 Snapshot(推荐)
|
||
|
||
```
|
||
MediaBot 启动 / 定时任务:
|
||
1. GET /api/v1/manifest → 获取全量站点列表
|
||
2. 对每个站点:
|
||
a. GET /api/v1/snapshots/{siteId}/check → 获取最新 checksum
|
||
b. 与本地缓存的 checksum 比较
|
||
c. 不同时: GET /api/v1/snapshots/{siteId} → 拉取完整 bundle
|
||
d. 缓存 checksum 和完整 bundle
|
||
```
|
||
|
||
**优点**:
|
||
- 每次只需 1~2 次 HTTP 请求即可获取站点全部配置
|
||
- ETag/304 支持,配置未变时不传输内容
|
||
- 三层可用性保障(数据库 → CDN → 实时构建)
|
||
|
||
### 方案 B:渐进式迁移(兼容期)
|
||
|
||
```
|
||
1. 优先调用新接口 GET /api/v1/snapshots/{siteId}
|
||
2. PAR Server 不可用时 fallback 到 CDN:
|
||
- 直接 GET https://{CDN域名}/snapshots/{siteId}.json
|
||
3. CDN 也无数据时 fallback 到旧接口组合:
|
||
- GET /api/v1/configs/{siteId}/script
|
||
- GET /api/v1/sites/{siteId}/pages
|
||
- GET /api/v1/risk-rules/{siteType}
|
||
```
|
||
|
||
---
|
||
|
||
## 五、响应格式对比
|
||
|
||
### 旧方式(分散获取)
|
||
|
||
需要 **3~4 次 HTTP 请求** 才能凑齐一个站点的完整配置:
|
||
|
||
```
|
||
请求 1: GET /api/v1/configs/{siteId}/script → 返回 Groovy 脚本纯文本
|
||
请求 2: GET /api/v1/sites/{siteId}/pages → 返回页面入口配置
|
||
请求 3: GET /api/v1/risk-rules/{siteType} → 返回风险规则
|
||
请求 4: (可选) GET /api/v1/manifest → 返回全局站点列表
|
||
```
|
||
|
||
### 新方式(统一快照)
|
||
|
||
**1~2 次 HTTP 请求** 获取站点完整配置:
|
||
|
||
```
|
||
请求 1: GET /api/v1/snapshots/{siteId} (带 If-None-Match) → 返回完整 bundle
|
||
- 配置未变化: 304 Not Modified (0 流量)
|
||
- 配置有变化: 200 OK + 完整 JSON
|
||
|
||
(可选) 请求 0: GET /api/v1/manifest → 获取全量站点列表
|
||
```
|
||
|
||
### Bundle JSON 响应字段说明
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `siteId` | string | 站点标识 |
|
||
| `checksum` | string | 完整内容 SHA-256(用于 ETag) |
|
||
| `generatedAt` | string | 快照生成时间 (ISO 8601) |
|
||
| `script` | string | Groovy 脚本完整源码 |
|
||
| `scriptVersion` | string | 脚本版本号 |
|
||
| `scriptSource` | string | `"custom"` 或 `"default"` |
|
||
| `pages` | array | 页面入口配置条目列表 |
|
||
| `pagesVersion` | string | 页面配置版本号 |
|
||
| `pagesSource` | string | `"custom"` 或 `"default"` |
|
||
| `riskRules` | array | 风险规则列表 |
|
||
| `riskRulesVersion` | integer | 风险规则版本号 |
|
||
|
||
---
|
||
|
||
## 六、预览模式与两阶段发布
|
||
|
||
### 预览版 vs 正式版
|
||
|
||
PAR 快照分为两个状态:
|
||
|
||
| 状态 | 说明 | 谁可见 |
|
||
|------|------|--------|
|
||
| **预览版 (draft)** | 管理员保存后生效,未上传 CDN | MediaBot 带 `?preview=true` 可见 |
|
||
| **正式版 (published)** | 管理员发布后生效,已上传 CDN | 所有请求默认可见 |
|
||
|
||
### 两阶段发布工作流
|
||
|
||
```
|
||
开发者提交配置 → 管理员审核通过 → 自动生成预览版
|
||
↓
|
||
管理员保存预览版(savePreview)
|
||
↓
|
||
MediaBot 通过 ?preview=true 验证预览版效果
|
||
↓
|
||
管理员发布正式版(publish)
|
||
↓
|
||
快照写入 CDN,所有 MediaBot 自动获取最新版
|
||
```
|
||
|
||
### MediaBot 如何使用预览版
|
||
|
||
```bash
|
||
# 正常获取正式版(默认)
|
||
curl http://par:9012/api/v1/snapshots/pthome
|
||
|
||
# 获取预览版(用于开发/测试环境验证新配置)
|
||
curl "http://par:9012/api/v1/snapshots/pthome?preview=true"
|
||
```
|
||
|
||
> 💡 建议 MediaBot 在开发/测试环境使用 `?preview=true`,生产环境使用默认(正式版)。
|
||
|
||
---
|
||
|
||
## 七、鉴权说明
|
||
|
||
**无变化**。所有配置读取接口(snapshot、manifest、script、pages、risk-rules)均为**公开接口**,无需鉴权。提交类接口需 HMAC/PSK 或 JWT 认证。
|
||
|
||
---
|
||
|
||
## 八、迁移时间线建议
|
||
|
||
| 阶段 | 时间 | 操作 |
|
||
|------|------|------|
|
||
| **Phase 1** | 立即 | MediaBot 开始调用 `/snapshots/{siteId}` 作为主路径,旧接口作为 fallback |
|
||
| **Phase 2** | 稳定运行 2 周后 | 移除旧接口 fallback 逻辑 |
|
||
| **Phase 3** | 后续版本 | 视情况废弃分散获取接口(script/pages/rules 独立端点) |
|
||
|
||
---
|
||
|
||
## 九、FAQ
|
||
|
||
**Q: 旧接口会下线吗?**
|
||
A: 短期内不会。但建议尽快迁移到 snapshot 接口以获得更好的性能和可用性。
|
||
|
||
**Q: snapshot 接口响应时间会不会更长?**
|
||
A: 不会。数据库查询是单次 SQL(按 site_id + status 索引),且应用层有 Caffeine 缓存。304 场景下完全不传输内容。
|
||
|
||
**Q: 如果 PAR Server 完全挂了怎么办?**
|
||
A: Snapshot 在发布时会同步上传到七牛云 CDN (`snapshots/{siteId}.json`),MediaBot 可以直接从 CDN 读取作为终极灾备。
|
||
|
||
**Q: checksum 是用什么算法计算的?**
|
||
A: SHA-256,对完整 bundle JSON 内容计算。
|
||
|
||
**Q: bundle 和 snapshot 的区别?**
|
||
A: 同一份数据。`/configs/{siteId}/bundle` 是兼容旧路径,`/snapshots/{siteId}` 是新路径,底层数据源相同。
|