290 lines
7.3 KiB
Markdown
290 lines
7.3 KiB
Markdown
|
|
# Sub2API 修改准备工作指南
|
|||
|
|
|
|||
|
|
**文档版本**:1.0
|
|||
|
|
**创建日期**:2026-03-23
|
|||
|
|
**基于版本**:Sub2API v0.1.104
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、项目技术栈
|
|||
|
|
|
|||
|
|
| 组件 | 版本 | 说明 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| **Go** | 1.25.7 (构建), 1.21+ (源码) | CI 使用 1.26.1 |
|
|||
|
|
| **Vue** | 3.4+ | 前端框架 |
|
|||
|
|
| **Vite** | 5+ | 前端构建工具 |
|
|||
|
|
| **PostgreSQL** | 15+ | 主数据库 |
|
|||
|
|
| **Redis** | 7+ | 缓存和队列 |
|
|||
|
|
| **Ent** | 0.14.5 | ORM 框架 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、测试基础设施
|
|||
|
|
|
|||
|
|
### 2.1 测试文件统计
|
|||
|
|
|
|||
|
|
| 类型 | 数量 | 位置 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| 单元测试 | 100+ | `backend/internal/**/*_test.go` |
|
|||
|
|
| 集成测试 | 3 | `backend/internal/integration/` |
|
|||
|
|
| E2E 测试 | 2 | `backend/internal/integration/e2e_*.go` |
|
|||
|
|
|
|||
|
|
### 2.2 测试模式
|
|||
|
|
|
|||
|
|
| 模式 | 使用文件数 | 说明 |
|
|||
|
|
|------|-----------|------|
|
|||
|
|
| **Table-Driven** | 30+ | 使用 `[]struct{}` 定义测试用例 |
|
|||
|
|
| **t.Run() 子测试** | 144+ | 参数化测试用例 |
|
|||
|
|
| **Custom Stubs** | 服务层 | 编译时接口实现 |
|
|||
|
|
| **Function Hook Mocks** | 仓库层 | 可选 Fn 字段覆盖行为 |
|
|||
|
|
| **TestContainers** | 集成测试 | PostgreSQL/Redis 容器 |
|
|||
|
|
|
|||
|
|
### 2.3 测试工具
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
backend/internal/testutil/
|
|||
|
|
├── stubs.go # 接口桩实现 (ConcurrencyCache, GatewayCache 等)
|
|||
|
|
├── fixtures.go # 测试数据构建器
|
|||
|
|
└── httptest.go # Gin 测试上下文辅助
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.4 测试构建标签
|
|||
|
|
|
|||
|
|
| 标签 | 命令 | 用途 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| `unit` | `go test -tags=unit ./...` | 单元测试(默认) |
|
|||
|
|
| `integration` | `go test -tags=integration ./...` | 集成测试 |
|
|||
|
|
| `e2e` | `go test -tags=e2e -v ./internal/integration/...` | E2E 测试 |
|
|||
|
|
|
|||
|
|
### 2.5 测试数据模型
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// fixtures.go 中的测试数据
|
|||
|
|
TestUser - ID:1, Email:test@example.com, Balance:100.0
|
|||
|
|
TestAccount - ID:1, Platform:Anthropic, Schedulable:true
|
|||
|
|
TestAPIKey - Key:"sk-test-key-12345678", GroupID:1
|
|||
|
|
TestGroup - ID:1, Platform:Anthropic
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.6 运行测试
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd backend
|
|||
|
|
|
|||
|
|
# 单元测试
|
|||
|
|
go test -tags=unit ./...
|
|||
|
|
|
|||
|
|
# 集成测试(需要 PostgreSQL/Redis)
|
|||
|
|
go test -tags=integration ./...
|
|||
|
|
|
|||
|
|
# E2E 测试
|
|||
|
|
go test -tags=e2e -v -timeout=300s ./internal/integration/...
|
|||
|
|
|
|||
|
|
# 覆盖率
|
|||
|
|
go test -tags=unit -coverprofile=coverage.out ./...
|
|||
|
|
go tool cover -html=coverage.out -o coverage.html
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、代码生成模式
|
|||
|
|
|
|||
|
|
### 3.1 代码生成命令
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd backend
|
|||
|
|
|
|||
|
|
# 1. Ent ORM 代码生成(修改 schema 后必须)
|
|||
|
|
go generate ./ent
|
|||
|
|
|
|||
|
|
# 2. Wire 依赖注入代码生成(修改 wire.go 后必须)
|
|||
|
|
go generate ./cmd/server
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.2 Wire 依赖注入架构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
backend/cmd/server/
|
|||
|
|
├── wire.go # Provider 定义(使用 //go:build wireinject)
|
|||
|
|
└── wire_gen.go # 自动生成(禁止手动编辑)
|
|||
|
|
|
|||
|
|
各层 Provider 定义:
|
|||
|
|
├── internal/service/wire.go # 服务层 providers
|
|||
|
|
├── internal/handler/wire.go # 处理器层 providers
|
|||
|
|
├── internal/repository/wire.go # 仓库层 providers
|
|||
|
|
├── internal/config/wire.go # 配置 providers
|
|||
|
|
└── internal/server/middleware/wire.go # 中间件 providers
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.3 添加新服务的步骤
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 1. 在 wire.go 中添加 Provider
|
|||
|
|
# 例如在 internal/service/wire.go 添加:
|
|||
|
|
|
|||
|
|
func ProvideMyService(dep1 Dep1, dep2 Dep2) *MyService {
|
|||
|
|
return NewMyService(dep1, dep2)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 2. 在 ProviderSet 中注册
|
|||
|
|
var ProviderSet = wire.NewSet(
|
|||
|
|
// ... 现有 providers ...
|
|||
|
|
ProvideMyService,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 3. 重新生成 wire 代码
|
|||
|
|
go generate ./cmd/server
|
|||
|
|
|
|||
|
|
# 4. 如果修改了 Ent schema
|
|||
|
|
# 编辑 ent/schema/*.go
|
|||
|
|
go generate ./ent
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.4 数据库迁移
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
backend/migrations/
|
|||
|
|
├── 001_initial_schema.sql
|
|||
|
|
├── 002_*.sql
|
|||
|
|
├── ...
|
|||
|
|
└── 078_*.sql
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**迁移特性**:
|
|||
|
|
- 自动应用(启动时)
|
|||
|
|
- SHA256 校验验证
|
|||
|
|
- 支持非事务迁移(后缀 `_notx.sql`)
|
|||
|
|
- PostgreSQL Advisory Lock 多实例安全
|
|||
|
|
|
|||
|
|
**添加新迁移**:
|
|||
|
|
```bash
|
|||
|
|
# 创建新迁移文件
|
|||
|
|
cp migrations/078_*.sql migrations/079_your_migration.sql
|
|||
|
|
# 编辑迁移内容
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 四、项目已知问题
|
|||
|
|
|
|||
|
|
### 4.1 安全问题(需要修复)
|
|||
|
|
|
|||
|
|
| 问题 | 位置 | 影响 | 优先级 |
|
|||
|
|
|------|------|------|--------|
|
|||
|
|
| **跨实例 API Key 风险** | `api_key_service.go:248` | 其他部署的 Key 可在本实例使用 | 🔴 高 |
|
|||
|
|
| **跨实例兑换码风险** | `redeem_service.go:107` | 其他部署的兑换码可在本实例使用 | 🔴 高 |
|
|||
|
|
| **xlsx 依赖漏洞** | `audit-exceptions.yml` | GHSA-4r6h-8v6p-xvw6 | 🟡 中(2026-04-05 到期) |
|
|||
|
|
|
|||
|
|
### 4.2 已知的临时禁用功能
|
|||
|
|
|
|||
|
|
| 功能 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| **Sora 视频生成** | 上游集成问题,暂时不可用 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 五、升级兼容性
|
|||
|
|
|
|||
|
|
### 5.1 版本升级路径
|
|||
|
|
|
|||
|
|
| 方式 | 方法 | 说明 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| **二进制安装** | 管理后台 "Check for Updates" | 支持回滚 |
|
|||
|
|
| **Docker** | `docker compose pull && up -d` | 使用 local 版本便于迁移 |
|
|||
|
|
| **源码构建** | 重新构建前端+后端 | 必须使用 `-tags embed` |
|
|||
|
|
|
|||
|
|
### 5.2 高风险修改清单
|
|||
|
|
|
|||
|
|
| 修改内容 | 影响模块 | 风险等级 |
|
|||
|
|
|----------|----------|----------|
|
|||
|
|
| `APIKeyService.ValidateKey()` | 所有 API 认证 | 🔴 致命 |
|
|||
|
|
| `BillingService.CalculateCost()` | 所有计费计算 | 🔴 致命 |
|
|||
|
|
| `GatewayService.SelectAccountWithLoadAwareness()` | 负载均衡 | 🔴 致命 |
|
|||
|
|
| `UserRepo.DeductBalance()` | 余额扣减 | 🔴 致命 |
|
|||
|
|
| `BillingCacheService.CheckBalance()` | 请求拒绝 | 🟡 中等 |
|
|||
|
|
| `ConcurrencyService` | 并发控制 | 🟡 中等 |
|
|||
|
|
|
|||
|
|
### 5.3 架构关键点
|
|||
|
|
|
|||
|
|
- **核心网关**:`gateway_service.go` (8516 行),处理路由、计费、负载均衡
|
|||
|
|
- **粘性会话**:需要 Nginx 配置 `underscores_in_headers on`
|
|||
|
|
- **构建标志**:使用 `-tags embed` 嵌入前端资源
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 六、修改检查清单
|
|||
|
|
|
|||
|
|
### 6.1 修改前
|
|||
|
|
|
|||
|
|
- [ ] 阅读 `docs/REVIEW_AND_DEPENDENCIES.md` 了解跨模块依赖
|
|||
|
|
- [ ] 阅读受影响模块的代码
|
|||
|
|
- [ ] 理解测试覆盖范围
|
|||
|
|
- [ ] 准备测试用例
|
|||
|
|
|
|||
|
|
### 6.2 修改中
|
|||
|
|
|
|||
|
|
- [ ] 遵循 Wire Provider 模式添加新依赖
|
|||
|
|
- [ ] 使用 Ent 生成工具更新 ORM
|
|||
|
|
- [ ] 编写单元测试覆盖新代码
|
|||
|
|
- [ ] 使用 table-driven 测试模式
|
|||
|
|
|
|||
|
|
### 6.3 修改后
|
|||
|
|
|
|||
|
|
- [ ] 运行单元测试:`go test -tags=unit ./...`
|
|||
|
|
- [ ] 运行构建检查:`go build ./...`
|
|||
|
|
- [ ] 运行代码检查:`go vet ./...`
|
|||
|
|
- [ ] 格式化代码:`gofmt -s .`
|
|||
|
|
- [ ] 验证数据库迁移(如果有)
|
|||
|
|
|
|||
|
|
### 6.4 提交前
|
|||
|
|
|
|||
|
|
- [ ] 添加测试用例
|
|||
|
|
- [ ] 更新相关文档
|
|||
|
|
- [ ] 创建 PR 到主仓库(如果是 fork)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 七、GitHub 项目信息
|
|||
|
|
|
|||
|
|
| 项目 | 地址 |
|
|||
|
|
|------|------|
|
|||
|
|
| 主仓库 | https://github.com/Wei-Shaw/sub2api |
|
|||
|
|
| Issues | https://github.com/Wei-Shaw/sub2api/issues |
|
|||
|
|
| Releases | https://github.com/Wei-Shaw/sub2api/releases |
|
|||
|
|
|
|||
|
|
### 7.1 Release 流程
|
|||
|
|
|
|||
|
|
- 使用 `.goreleaser.yaml` 自动构建
|
|||
|
|
- 通过 Telegram 通知发布
|
|||
|
|
- GitHub Release 页面记录发布说明
|
|||
|
|
|
|||
|
|
### 7.2 当前版本
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
文件位置:backend/cmd/server/VERSION
|
|||
|
|
版本号:0.1.104
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 八、推荐的下一步
|
|||
|
|
|
|||
|
|
### 8.1 安全修复(高优先级)
|
|||
|
|
|
|||
|
|
1. 实施跨实例 API Key 验证
|
|||
|
|
2. 添加登录失败锁定机制
|
|||
|
|
|
|||
|
|
### 8.2 测试增强
|
|||
|
|
|
|||
|
|
1. 为关键路径补充集成测试
|
|||
|
|
2. 建立自动化回归测试
|
|||
|
|
|
|||
|
|
### 8.3 文档同步
|
|||
|
|
|
|||
|
|
1. 根据代码修改同步 `docs/` 中的模块文档
|
|||
|
|
2. 更新本指南中的修改检查清单
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
*本指南基于 Sub2API v0.1.104 代码审查生成*
|