github.com/qiniu/go-sdk/v7@v7.27.0/AGENTS.md (about) 1 # 七牛云 Go SDK — 开发维护指南 2 3 七牛云官方 Go SDK,模块路径 `github.com/qiniu/go-sdk/v7`,Go 1.22+,MIT 许可。 4 5 本文档面向 SDK 维护者和贡献者,帮助理解项目结构、架构模式和开发流程。 6 SDK 的 API 使用说明请参考各包的 `doc.go` 文件和 `examples/` 目录。 7 8 ## 项目结构 9 10 ### 顶层包 11 12 | 包 | 职责 | 13 |---|------| 14 | `auth` | 认证凭证(AK/SK)、HMAC-SHA1 签名、上传凭证、回调验证 | 15 | `storage` | 对象存储 v1:表单上传、分片上传、Bucket/对象管理、数据处理(pfop) | 16 | `storagev2` | 对象存储 v2:类型化 API、自动区域检测、连接池、重试、Provider/Interface 模式 | 17 | `cdn` | CDN 加速:刷新、预取、流量/带宽查询、时间戳防盗链 | 18 | `pili` | 直播云:流管理、域名管理、推拉流地址生成 | 19 | `rtc` | 实时音视频:应用管理、房间 Token、用户管理 | 20 | `sms` | 短信:发送短信、签名/模板管理 | 21 | `linking` | IoT 设备联网:设备管理、密钥、录像片段 | 22 | `qvs` | 视频监控(QVS):GB/T 28181 设备接入、空间/设备/流管理 | 23 | `iam` | 身份与访问管理:用户、组、策略 CRUD(生成代码) | 24 | `media` | 多媒体处理:Pfop 触发/Prefop 查询(生成代码) | 25 | `audit` | 审计日志:日志查询(生成代码) | 26 | `sandbox` | 沙箱环境:创建/管理沙箱、文件操作、命令执行、PTY 终端 | 27 | `client` | 底层 HTTP 客户端:请求签名、JSON/表单序列化、错误解析 | 28 | `conf` | 全局配置:SDK 版本号(`conf.Version`)、User-Agent 设置 | 29 | `reqid` | 请求 ID:通过 Context 传递 X-Reqid | 30 31 ### internal 包 32 33 | 包 | 职责 | 34 |---|------| 35 | `internal/api-generator` | 代码生成器:读取 YAML API 规范生成类型化 Go 代码 | 36 | `internal/clientv2` | HTTP 客户端 v2:拦截器链模式、认证注入、重试、防劫持 | 37 | `internal/cache` | 通用缓存 | 38 | `internal/hostprovider` | 主机地址提供者 | 39 | `internal/freezer` | 主机冻结/降级 | 40 | `internal/context` | Context 兼容层 | 41 | `internal/env` | 环境变量读取 | 42 | `internal/log` | 内部日志 | 43 | `internal/uplog` | 上传日志 | 44 | `internal/io` | IO 工具 | 45 | `internal/dialer` | 网络拨号 | 46 | `internal/configfile` | 配置文件读取 | 47 48 ### storagev2 子包 49 50 | 包 | 职责 | 51 |---|------| 52 | `storagev2/apis` | 低级 API 客户端,所有方法由代码生成器生成 | 53 | `storagev2/apistest` | API mock/测试辅助 | 54 | `storagev2/credentials` | 凭证管理(Provider 接口) | 55 | `storagev2/http_client` | HTTP 客户端选项、拦截器集成 | 56 | `storagev2/region` | 区域信息(RegionsProvider 接口) | 57 | `storagev2/uploader` | 上传管理器(自动选择上传方式) | 58 | `storagev2/downloader` | 下载管理器 | 59 | `storagev2/objects` | 对象管理(流式 API) | 60 | `storagev2/uptoken` | 上传凭证(PutPolicy → Signer) | 61 | `storagev2/backoff` | 重试退避策略 | 62 | `storagev2/chooser` | 主机选择器 | 63 | `storagev2/resolver` | 域名解析器 | 64 | `storagev2/retrier` | 重试器 | 65 | `storagev2/defaults` | 默认配置值 | 66 | `storagev2/errors` | 类型化错误 | 67 | `storagev2/uplog` | 上传日志 | 68 | `storagev2/internal` | storagev2 内部实现 | 69 70 ### 其他目录 71 72 | 目录 | 说明 | 73 |------|------| 74 | `api-specs/` | API 规范(git submodule),包含 storage、iam、media、audit、sandbox 的 YAML/OpenAPI 定义 | 75 | `examples/` | 各功能的使用示例,每个示例是独立子目录(独立 `main` 包) | 76 77 ## 核心架构模式 78 79 ### Manager 模式(storage v1) 80 81 v1 的对象存储使用 Manager 模式,每个功能域对应一个 Manager 结构体: 82 83 - `storage.BucketManager` — Bucket 和对象管理 84 - `storage.FormUploader` / `storage.ResumeUploader` — 上传 85 - `storage.OperationManager` — 数据处理 86 87 构造方式统一为 `New*(mac, &cfg)` 或 `New*(&cfg)`,通过 `auth.Credentials` 传递认证信息。 88 89 ### Provider/Interface 模式(storagev2) 90 91 v2 通过接口抽象实现可插拔: 92 93 - `credentials.CredentialsProvider` — 凭证提供者 94 - `region.RegionsProvider` — 区域信息提供者 95 - `chooser.Chooser` — 主机选择策略 96 - `resolver.Resolver` — 域名解析 97 - `retrier.Retrier` — 重试策略 98 - `backoff.Backoff` — 退避策略 99 100 所有组件通过 `http_client.Options` 注入,支持自定义替换。 101 102 ### Interceptor 拦截器链(internal/clientv2) 103 104 HTTP 请求通过拦截器链处理,拦截器按优先级排序(数字越小优先级越高): 105 106 ``` 107 RetryHosts(200) → RetrySimple(300) → Uplog(310) → BufferResponse(320) 108 → SetHeader(400) → Normal(500) → Auth(600) → AntiHijacking(700) → Debug(800) 109 ``` 110 111 核心接口: 112 113 ```go 114 type Interceptor interface { 115 Priority() InterceptorPriority 116 Intercept(req *http.Request, handler Handler) (*http.Response, error) 117 } 118 ``` 119 120 ### Context 传递认证 121 122 storage v1 通过函数参数传递 `auth.Credentials`,storagev2 通过 `http_client.Options` 结构体传递。`reqid` 包提供 Context 传递请求 ID 的机制(`X-Reqid` 头)。 123 124 ### 双版本共存 125 126 `storage`(v1)和 `storagev2`(v2)并行维护: 127 - v1:稳定的对外 API,Manager 模式,手写代码 128 - v2:新一代 API,Provider/Interface 模式,代码生成 + 手写 129 - 两者共享 `auth`、`client`、`conf`、`reqid` 等基础包 130 - 新功能优先在 v2 实现,v1 仅做维护性修改 131 132 ## 代码生成 133 134 ### API 代码生成(make generate) 135 136 `internal/api-generator` 读取 `api-specs/` 中的 YAML 规范,生成类型化 Go 代码: 137 138 ``` 139 api-specs/<service>/*.yml → internal/api-generator → <service>/apis/*.go 140 ``` 141 142 涉及的包及 `//go:generate` 指令: 143 - `storagev2/` → `storagev2/apis/`(struct: Storage) 144 - `iam/` → `iam/apis/`(struct: IAM) 145 - `media/` → `media/apis/`(struct: Media) 146 - `audit/` → `audit/apis/`(struct: Audit) 147 148 运行命令: 149 150 ```bash 151 make generate # 运行所有 go generate 并格式化代码 152 ``` 153 154 ### Sandbox 代码生成(make generate-sandbox) 155 156 sandbox 使用不同的生成工具链: 157 158 - **控制面 API**:`oapi-codegen`(OpenAPI → Go)→ `sandbox/internal/apis/` 159 - **envd HTTP API**:`oapi-codegen` → `sandbox/internal/envdapi/` 160 - **envd ConnectRPC**:`buf` + `protoc-gen-go` + `protoc-gen-connect-go` → `sandbox/internal/envdapi/` 161 162 运行命令: 163 164 ```bash 165 make generate-sandbox # 需要安装 buf、protoc-gen-go、protoc-gen-connect-go 166 ``` 167 168 ### 生成代码标记 169 170 所有生成的代码文件首行包含如下标记之一: 171 172 - `// THIS FILE IS GENERATED BY api-generator, DO NOT EDIT DIRECTLY!` 173 - `// Code generated by protoc-gen-go. DO NOT EDIT.` 174 - `// Code generated by protoc-gen-connect-go. DO NOT EDIT.` 175 - `// Code generated by github.com/oapi-codegen/oapi-codegen/v2 ... DO NOT EDIT.` 176 177 **绝对不要手动修改这些文件**,如需修改请更新对应的 API 规范后重新生成。 178 179 ## 编码规范 180 181 ### 格式化 182 183 - 使用 `gofmt -s` 格式化代码(CI 会检查) 184 - `make generate` 会自动运行 `gofmt -w .` 和 `gofumpt -w .` 185 186 ### 静态检查 187 188 - 使用 `staticcheck`(CI 会检查) 189 - 运行:`make staticcheck` 190 191 ### 注释规范 192 193 - 注释默认使用**中文** 194 - 导出的 API、函数、类型、常量、变量必须添加注释 195 - 注释以被注释的标识符名称开头(符合 Go 官方 godoc 规范) 196 - 包级别注释写在 `doc.go` 的 `package` 声明之前 197 198 ### 命名规范 199 200 - 构造函数使用 `New*()` 或 `New*Ex()` 命名 201 - 错误类型:根包使用 `client.ErrorInfo`(Code + Err + Reqid),storagev2 使用 `storagev2/errors` 包 202 203 ### 错误处理 204 205 - 错误使用 Go 标准的 `fmt.Errorf("context: %w", err)` 包装 206 - 使用 `errors.Is()` / `errors.As()` 判断错误类型 207 208 ## 测试规范 209 210 ### Build Tags 211 212 测试文件必须添加 build tag: 213 214 ```go 215 //go:build unit 216 217 package xxx_test 218 ``` 219 220 - `unit` — 单元测试,不依赖外部服务 221 - `integration` — 集成测试,需要七牛账号和网络 222 223 ### Makefile 测试命令 224 225 | 命令 | 说明 | 226 |------|------| 227 | `make unittest` | 运行单元测试(提交前必须通过) | 228 | `make integrationtest` | 运行集成测试(需要环境变量配置) | 229 | `make test` | 运行所有测试 | 230 231 所有测试命令排除 `examples/` 和 `sms/` 目录。 232 233 ### 测试实践 234 235 - 使用 `testify/assert` 进行断言 236 - 推荐使用表驱动测试 237 - mock 测试可参考 `storagev2/apistest` 包 238 239 ## CI 流程 240 241 CI 在 push 和 pull_request 时触发(`.github/workflows/ci-test.yml`): 242 243 ### Linux(主要检查) 244 245 Go 1.22 + stable 两个版本矩阵: 246 247 1. **gofmt 检查**(仅 stable):`gofmt -s -l .` 检查未格式化文件 248 2. **staticcheck**(仅 stable):`make staticcheck` 249 3. **编译 examples**(仅 stable):`go build ./examples/...` 250 4. **单元测试**(两个版本):`make unittest` 251 252 ### Windows / macOS 253 254 Linux 通过后依次运行,仅执行 `make unittest`(stable 版本)。 255 256 ### 版本检查 257 258 发布 tag 时(`.github/workflows/version-check.yml`),检查以下三处版本号一致: 259 260 - `CHANGELOG.md` 包含 `## <version>` 261 - `README.md` 包含 `require github.com/qiniu/go-sdk/v7 v<version>` 262 - `conf/conf.go` 包含 `const Version = "<version>"` 263 264 ## 开发工作流 265 266 ### 环境准备 267 268 ```bash 269 # 初始化 api-specs submodule 270 git submodule update --init --recursive 271 272 # 验证当前状态 273 make unittest 274 make staticcheck 275 ``` 276 277 ### 日常开发 278 279 1. 确保分支基于最新 master:`git fetch upstream && git rebase upstream/master` 280 2. 修改代码前先运行 `make unittest` 确认当前状态 281 3. 修改 API 规范后运行 `make generate` 或 `make generate-sandbox` 282 4. 提交前运行 `make unittest` 和 `make staticcheck` 确保通过 283 5. 代码格式化:`gofmt -s -w .` 284 285 ### 修改生成代码的正确流程 286 287 1. 更新 `api-specs/` 中对应的 YAML 规范(如需) 288 2. 运行 `make generate`(或 `make generate-sandbox`) 289 3. 检查生成结果,确认无误后提交规范和生成代码 290 291 ### 测试与验证 292 293 实现新功能或修复 bug 时,应同时提供单元测试和集成测试。对于涉及幂等、重试等逻辑的接口,单元测试用 mock 覆盖边界条件,集成测试用真实凭证验证端到端行为。 294 295 #### 运行规则 296 297 ```bash 298 # 单测(提交前必须通过) 299 make unittest 300 301 # 特定包的单测 302 go test -tags=unit -count=1 -v ./sandbox/ 303 304 # 集成测试(需要 .env 文件) 305 set -a && source sandbox/.env && set +a && go test -tags=integration -count=1 -v ./sandbox/ 306 ``` 307 308 #### 环境变量 `.env` 文件 309 310 `sandbox/.env` 用于集成测试和示例程序的环境变量配置: 311 312 ``` 313 QINIU_API_KEY= # 七牛 API Key(必填) 314 QINIU_SANDBOX_API_URL= # API 端点(可选,默认 https://cn-yangzhou-1-sandbox.qiniuapi.com) 315 SANDBOX_RETRY_MAX= # 可重试 API 的最大重试次数(可选,默认 5,设为 0 禁用重试) 316 ``` 317 318 使用方式: 319 320 ```bash 321 cd sandbox/ 322 set -a && source .env && set +a 323 # 后续 go test / go run 命令可直接读取环境变量 324 ``` 325 326 #### 运行示例 327 328 ```bash 329 # 需要先 source sandbox/.env 330 go run ./examples/sandbox_idempotency_retry/ 331 ``` 332 333 ## 重要约定 334 335 1. **不要手动修改生成代码** — 带 `DO NOT EDIT DIRECTLY` 标记的文件由代码生成器维护 336 2. **不要删除 sms 测试排除** — Makefile 中 `egrep -v 'examples|sms'` 是有意为之 337 3. **examples 是独立子目录** — 每个示例是独立的 `main` 包,编译方式为 `go build ./examples/...` 338 4. **版本号三处同步** — 发布时确保 `conf/conf.go`、`CHANGELOG.md`、`README.md` 版本一致 339 5. **api-specs 是 git submodule** — 更新规范需要在 submodule 中操作 340 6. **保持双版本兼容** — storage v1 和 storagev2 v2 并行维护,不要在 v1 中引入 v2 的依赖