Files
happy-life-star/docs/superpowers/specs/2026-05-23-api-endpoint-management-design.md
T
peanut a4c99b9b0b feat: 接口管理功能 - 分页查询、详情查看、测试代理
- 后端:OpenAPI spec 解析同步、接口分页查询、代理测试(SSRF防护)
- 前端:接口列表页、详情对话框(详情/测试双标签)、Token来源选择
- 服务启动自动同步接口数据,支持手动触发同步
- 测试代理路径修复:自动添加 /api 前缀以匹配后端 SSRF 校验

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 19:19:08 +08:00

156 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
author: Peanut
created_at: 2026-05-23
purpose: 设计 web-admin 接口管理功能,通过解析 OpenAPI JSON 实现接口发现、管理和测试
---
# 接口管理功能设计文档
## 1. 架构概览
Spring Boot 启动时通过 ApplicationRunner 解析本机 `/api/v3/api-docs` 的 OpenAPI JSON,在事务中全量更新数据库(删除旧数据 → 解析 → 批量插入)。前端从数据库查询接口列表,支持分页、按标签/方法/路径/operationId 搜索。接口测试面板支持三种 Token 来源:当前管理员 Token、手动输入、用户端登录获取并自动保存。后端提供代理测试接口,仅限管理员访问,仅允许转发到本地 `/api/*` 路径,避免 SSRF。
## 2. 数据库设计
### 接口主表 api_endpoint
```sql
CREATE TABLE api_endpoint (
id VARCHAR(64) PRIMARY KEY,
path VARCHAR(500) NOT NULL,
method VARCHAR(10) NOT NULL,
operation_id VARCHAR(200),
summary VARCHAR(500),
description TEXT,
tags VARCHAR(500),
deprecated TINYINT(1) DEFAULT 0,
request_schema JSON,
response_schema JSON,
create_by VARCHAR(64),
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
update_by VARCHAR(64),
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
is_deleted TINYINT(1) DEFAULT 0,
remarks VARCHAR(500),
UNIQUE INDEX idx_operation_id (operation_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
### 参数表 api_param
```sql
CREATE TABLE api_param (
id VARCHAR(64) PRIMARY KEY,
endpoint_id VARCHAR(64) NOT NULL,
param_type VARCHAR(20) NOT NULL,
name VARCHAR(100) NOT NULL,
required TINYINT(1) DEFAULT 0,
param_type_def VARCHAR(50),
description VARCHAR(500),
default_value VARCHAR(200),
enum_values JSON,
example VARCHAR(500),
INDEX idx_endpoint (endpoint_id),
FOREIGN KEY (endpoint_id) REFERENCES api_endpoint(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
**说明**:实体类继承项目已有的 `BaseEntity`(含 id、createBy、createTime、updateBy、updateTime、isDeleted、remarks),使用 `IdType.ASSIGN_UUID` 生成 UUID 主键。
## 3. 后端服务设计
### 新增文件
| 文件 | 职责 |
|---|---|
| `entity/ApiEndpoint.java` | 继承 BaseEntity |
| `entity/ApiParam.java` | 继承 BaseEntity |
| `mapper/ApiEndpointMapper.java` | BaseMapper<ApiEndpoint> |
| `mapper/ApiParamMapper.java` | BaseMapper<ApiParam> |
| `dto/request/ApiEndpointListRequest.java` | 继承 BasePageRequest,添加 method、tags 过滤 |
| `dto/response/ApiEndpointItemResponse.java` | 列表项 |
| `dto/response/ApiEndpointDetailResponse.java` | 详情 + 参数列表 |
| `dto/request/ApiTestProxyRequest.java` | 代理测试入参 |
| `service/ApiEndpointService.java` | 解析 OpenAPI JSON、同步、查询 |
| `service/ApiEndpointSyncRunner.java` | @Component + ApplicationRunner,启动时触发 |
| `controller/ApiEndpointController.java` | 路由前缀 /endpoint |
| `controller/ApiTestProxyController.java` | 路由前缀 /endpoint/test,管理员专用 |
### 同步逻辑(ApiEndpointService.syncFromOpenApi()
1. 通过 RestTemplate 请求 `http://127.0.0.1:{port}/api/v3/api-docs`port 从配置文件读取)
2. 若请求失败,记录 WARN 日志,不阻断启动
3. `@Transactional` 包裹:DELETE FROM api_param → DELETE FROM api_endpoint
4. 遍历 `paths``method` → 解析每个 endpoint
5. 提取 tags、summary、description、operationId、requestSchema、responseSchema
6.`parameters` 数组解析参数列表(query/path/header/cookie
7.`requestBody.content` 解析 body schema
8. `$ref` 展开为内联 schema,最大展开深度 10 层
9. 批量插入 endpoint → 批量插入 param
### 后端接口(无 /api 前缀,通过网关转发)
| 方法 | 路径 | 说明 | 权限 |
|---|---|---|---|
| POST | /admin/endpoint/list | 分页查询,关键词同时搜索 path/summary/operation_id | 管理员 |
| GET | /admin/endpoint/detail | 查询详情 + 参数列表 | 管理员 |
| POST | /admin/endpoint/sync | 手动触发同步,同步耗时较长,返回 task ID | 管理员 |
| POST | /admin/endpoint/test | 代理测试请求,仅允许 /api/* 路径 | 管理员 |
### 代理测试安全控制
- 仅允许转发到 `/api/*` 路径,拒绝其他 URL(SSRF 防护)
- 仅管理员可访问(AdminAuthInterceptor 拦截 /admin/**
- 默认 30s 超时,超时返回明确错误信息
- 非 JSON 响应限制展示前 2000 字符,HTML 内容做转义处理
### 同步接口异步化
手动同步(`/admin/endpoint/sync`)采用 `@Async` 异步执行,返回 `{ taskId: "xxx" }`,前端通过轮询 `/admin/endpoint/sync/status/{taskId}` 获取同步进度和结果。ApplicationRunner 的启动同步同样异步,不阻塞应用启动。
## 4. 前端页面设计
### 菜单位置
在现有 **开发工具** 分组下新增 "接口管理" 子菜单。
### 接口列表页
- 搜索条件:关键词(覆盖 path、summary、operation_id)、HTTP 方法下拉、标签下拉
- 表格列:方法(颜色标签区分)、路径、简述、标签、更新时间
- 操作列:[详情] 按钮
- 顶部:[手动同步] 按钮(触发后显示同步进度提示)
### 接口详情/测试弹窗
点击"详情"弹出对话框,包含两个标签页:
**详情标签**
- 路径、方法、描述
- 参数列表表格(类型、名称、必填、描述、示例)
- 响应结构 JSON 展示
**测试标签**
- Token 来源选择(单选):
- 使用当前管理员 Token(默认)
- 手动输入文本框
- 用户端登录获取(输入手机号/验证码,成功后自动保存 Token 到 localStorage
- 参数表单:根据接口参数自动生成输入框
- [发送请求] 按钮
- 响应结果区域:状态码、耗时、JSON 格式化展示
## 5. 错误处理与边界情况
| 场景 | 处理方式 |
|---|---|
| `/v3/api-docs` 请求失败 | 记录 WARN 日志,不阻断启动,提供手动同步 |
| 同步中途异常 | `@Transactional` 回滚,下次同步全量替换 |
| 数据库为空 | 前端显示空状态提示 + 手动同步按钮 |
| 测试代理超时 | 返回 `Result.error("代理请求超时(30s),目标接口可能响应过慢或不可达")` |
| 非 JSON 响应 | 展示前 2000 字符,HTML 转义,二进制返回类型提示 |
| Token 保存 | 管理员 Token 走现有机制,手动 Token 仅内存使用,用户端 Token 存 localStorage |
| `$ref` 循环引用 | 最大展开深度 10 层,超限保留 `$ref` 并提示 |
| 文件上传接口 | 本期不支持,后续迭代 |