resource 模块
文件 / 对象存储与实时推送模块。承担 OSS 上传 / 下载 / 列表 / 删除、OSS 配置 CRUD(默认状态切换 + 启动时缓存预热)、消息箱读取端点、短信 / 邮箱验证码端点(按手机号 / 邮箱限流)、SSE / WebSocket 推送连接端点( RegisterPushRoutes,受 push.enabled 条件开启)。
前缀:standalone /resource,modular ""。探针:GET /resource/ping。
业务路由
| 方法 | 路径 | 鉴权 | 中间件 | Handler |
|---|---|---|---|---|
| GET | /message/box | CheckLogin | — | MessageApiApp.GetBox |
| GET | /sms/code | public(sagin.Ignore()) | ratelimiter.RateLimiterWithKeyFunc(1m,1,key=phoneNumber) | CaptchaApiApp.SmsCode |
| GET | /email/code | public(sagin.Ignore()) | ratelimiter.RateLimiterWithKeyFunc(1m,1,key=email) | CaptchaApiApp.EmailCode |
| GET | /oss/config/list | system:ossConfig:list | — | OssConfigApiApp.List |
| GET | /oss/config/:ossConfigId | system:ossConfig:list | — | OssConfigApiApp.GetInfo |
| POST | /oss/config | system:ossConfig:add | OP(ossConfig,Insert) RS | OssConfigApiApp.Add |
| PUT | /oss/config | system:ossConfig:edit | OP(ossConfig,Update) RS | OssConfigApiApp.Edit |
| PUT | /oss/config/changeStatus | system:ossConfig:edit | OP(ossConfigStatus,Update) RS | OssConfigApiApp.ChangeStatus |
| DELETE | /oss/config/:ossConfigIds | system:ossConfig:remove | OP(ossConfig,Delete) | OssConfigApiApp.Remove |
| GET | /oss/list | system:oss:list | — | OssApiApp.List |
| GET | /oss/listByIds/:ossIds | system:oss:query | — | OssApiApp.ListByIDs |
| GET | /oss/download/:ossId | system:oss:download | — | OssApiApp.Download |
| POST | /oss/upload | system:oss:upload | OP(oss,Insert, WithoutRequestData())(无 RS) | OssApiApp.Upload |
| DELETE | /oss/:ossIds | system:oss:remove | OP(oss,Delete) | OssApiApp.Remove |
| GET | /ping | public | — | inline {"module":"resource",...} |
中间件图例:OP=oplog.Log(title,type),RS=repeatsubmit.RepeatSubmit(0,""),ENC=encrypt.ApiEncrypt()。
推送路由
RegisterPushRoutes,仅当 config.Get().Push.Enabled 时注册:
| 方法 | 路径 | 鉴权 | 中间件 | Handler |
|---|---|---|---|---|
| GET | <prefix>/<push.path>(默认 /message) | CheckLogin | push.NormalizeQueryToken(), TokenInterceptor | push.Handler() |
| GET | <prefix>/<push.path>/close | CheckLogin | push.NormalizeQueryToken(), TokenInterceptor | push.CloseHandler() |
- standalone:
/resource/message+/resource/message/close - modular:
/message+/message/close
Services
位于 internal/resource/service/:
| Service(单例) | 职责 |
|---|---|
OssConfigService(OssConfigSvcApp) | OSS 配置 CRUD、key 唯一性、默认状态切换、启动时缓存预热(InitCache);保护 4 个内置配置不可删。 |
OssService(OssSvcApp) | 文件上传(生成新 key、持久化元数据)、下载(私有桶预签 120s TTL)、list / listByIds、删除;对象 I/O 委派 pkg/oss。 |
TIP
CaptchaApiApp 与 MessageApiApp 这两个 handler 分别委派给 auth 的 captcha 服务与 system 的 MessageSvcApp——resource 模块不为它们提供本地 service。
设计要点
路由注册顺序
/oss/config 刻意先于 /oss 注册——避免 DELETE /oss/config/:ids 被 DELETE /oss/:ossIds 吞掉。
upload 无 RepeatSubmit——重传同一文件是合法行为(每次生成新 key,不覆盖)。upload 带 oplog WithWithoutRequestData(),避免 oplog 把 multipart body 解析进内存。
OSS 配置 changeStatus 带 RepeatSubmit(与 system 的 client changeStatus 幂等不同)——OSS 默认切换需先把全表置非默认再设目标行,并发重复创建会出现无默认配置的窗口。
短信 / 邮箱验证码端点 public(Ignore)但按手机号 / 邮箱限流 1 次/60s;位于受保护组(有 TokenInterceptor)内,故 Ignore 必填。
推送 token 归一化 推送路由需 push.NormalizeQueryToken() 在 TokenInterceptor 之前——EventSource /
WebSocket 无法设自定义头,token 经 ?Authorization=Bearer xxx 传入;sa-token-go 的 query 分支不剥离 Bearer 前缀,必须先归一化。
OSS 配置详情复用 list 权限码。OSS 权限码命名空间为 system:oss:* / system:ossConfig:*(即便由 resource 模块提供,仍遵循 system: 前缀约定)。
message/box 由 resource 进程提供,但业务逻辑(MessageSvcApp.QueryMessageBox)位于 internal/system/service——modular 部署时 resource 进程以 in-process 方式调用,不走 HTTP。