175 lines
4.6 KiB
Markdown
175 lines
4.6 KiB
Markdown
# httpapi 包参考
|
||
|
||
本文档覆盖 `internal/httpapi/handler.go`,说明 HTTP 路由注册和各处理函数与服务层的映射关系。
|
||
|
||
## 包职责
|
||
|
||
`internal/httpapi` 负责把 `service.Service` 暴露成 HTTP 接口。当前只承担:
|
||
|
||
- 健康检查
|
||
- 运行状态查询
|
||
- 立即触发任务
|
||
- 运行镜像身份查询
|
||
|
||
它不包含业务逻辑,所有计费行为都委托给 `service.Service`。
|
||
|
||
## 类型
|
||
|
||
### `Handler`
|
||
|
||
签名:`type Handler struct`
|
||
|
||
| 字段 | 类型 | 含义 |
|
||
| --- | --- | --- |
|
||
| `service` | `*service.Service` | 业务服务实例 |
|
||
|
||
## 函数与方法
|
||
|
||
### `New`
|
||
|
||
- 签名:`func New(svc *service.Service) *Handler`
|
||
- 参数:
|
||
- `svc`:业务服务实例
|
||
- 返回:
|
||
- `*Handler`
|
||
- 职责:
|
||
- 构造 HTTP handler
|
||
- 调用位置:
|
||
- `cmd/billing-service/main.go`
|
||
- 主要副作用:无
|
||
- 错误/边界条件:
|
||
- 不校验 `svc` 是否为 `nil`
|
||
|
||
### `Routes`
|
||
|
||
- 签名:`func (h *Handler) Routes() http.Handler`
|
||
- 参数:无
|
||
- 返回:
|
||
- `http.Handler`:注册好全部路由的 `*http.ServeMux`
|
||
- 职责:
|
||
- 注册当前服务支持的全部 HTTP 路径
|
||
- 调用位置:
|
||
- `cmd/billing-service/main.go`
|
||
- 主要副作用:
|
||
- 构造新的 `ServeMux`
|
||
- 错误/边界条件:
|
||
- 当前路由集合固定,不包含版本协商或中间件
|
||
|
||
当前注册的路由:
|
||
|
||
| 路径 | 处理函数 | 说明 |
|
||
| --- | --- | --- |
|
||
| `/api/ping` | `ping` | 返回运行镜像身份 |
|
||
| `/healthz` | `healthz` | 返回最近一次任务健康状态 |
|
||
| `/v1/status` | `status` | 返回最近一次任务结果快照 |
|
||
| `/v1/jobs/collect-and-rate` | `collectAndRate` | 触发立即采集与计费 |
|
||
| `/v1/jobs/reconcile` | `reconcile` | 触发同一执行路径,但 job 名不同 |
|
||
|
||
### `ping`
|
||
|
||
- 签名:`func (h *Handler) ping(w http.ResponseWriter, r *http.Request)`
|
||
- 参数:`w`、`r`
|
||
- 返回:无
|
||
- 职责:
|
||
- 返回 `service.Ping()` 的结果
|
||
- 调用位置:
|
||
- `Routes`
|
||
- 主要副作用:
|
||
- 写 HTTP 响应
|
||
- 错误/边界条件:
|
||
- 当前不限制 HTTP 方法,任何方法都会返回 `200`
|
||
|
||
### `healthz`
|
||
|
||
- 签名:`func (h *Handler) healthz(w http.ResponseWriter, r *http.Request)`
|
||
- 参数:`w`、`r`
|
||
- 返回:无
|
||
- 职责:
|
||
- 调用 `service.Health()`
|
||
- 将布尔健康值映射为 HTTP 状态码与 `status` 文本
|
||
- 调用位置:
|
||
- `Routes`
|
||
- 主要副作用:
|
||
- 写 HTTP 响应
|
||
- 错误/边界条件:
|
||
- `ok == false` 时返回 `503`
|
||
- 当前不限制 HTTP 方法
|
||
|
||
### `status`
|
||
|
||
- 签名:`func (h *Handler) status(w http.ResponseWriter, r *http.Request)`
|
||
- 参数:`w`、`r`
|
||
- 返回:无
|
||
- 职责:
|
||
- 返回最近一次 `service.Status()`
|
||
- 调用位置:
|
||
- `Routes`
|
||
- 主要副作用:
|
||
- 写 HTTP 响应
|
||
- 错误/边界条件:
|
||
- 当前不限制 HTTP 方法
|
||
|
||
### `collectAndRate`
|
||
|
||
- 签名:`func (h *Handler) collectAndRate(w http.ResponseWriter, r *http.Request)`
|
||
- 参数:`w`、`r`
|
||
- 返回:无
|
||
- 职责:
|
||
- 只接受 `POST`
|
||
- 调用 `service.RunCollectAndRate(r.Context(), "collect-and-rate")`
|
||
- 根据是否返回错误决定 `200` 或 `503`
|
||
- 调用位置:
|
||
- `Routes`
|
||
- 主要副作用:
|
||
- 触发一次完整计费执行
|
||
- 写 HTTP 响应
|
||
- 错误/边界条件:
|
||
- 非 `POST` 返回 `405 method not allowed`
|
||
- 服务层返回错误时仍返回 `JobResult`,但状态码为 `503`
|
||
|
||
### `reconcile`
|
||
|
||
- 签名:`func (h *Handler) reconcile(w http.ResponseWriter, r *http.Request)`
|
||
- 参数:`w`、`r`
|
||
- 返回:无
|
||
- 职责:
|
||
- 只接受 `POST`
|
||
- 调用 `service.RunCollectAndRate(r.Context(), "reconcile")`
|
||
- 与 `collectAndRate` 共用同一业务路径,仅 job 名不同
|
||
- 调用位置:
|
||
- `Routes`
|
||
- 主要副作用:
|
||
- 触发一次完整计费执行
|
||
- 写 HTTP 响应
|
||
- 错误/边界条件:
|
||
- 非 `POST` 返回 `405`
|
||
- 服务层返回错误时状态码为 `503`
|
||
|
||
### `writeJSON`
|
||
|
||
- 签名:`func writeJSON(w http.ResponseWriter, status int, payload any)`
|
||
- 参数:
|
||
- `w`:响应写入器
|
||
- `status`:HTTP 状态码
|
||
- `payload`:任意可 JSON 编码的对象
|
||
- 返回:无
|
||
- 职责:
|
||
- 统一设置 `Content-Type: application/json`
|
||
- 写入状态码和 JSON 响应体
|
||
- 调用位置:
|
||
- `ping`
|
||
- `healthz`
|
||
- `status`
|
||
- `collectAndRate`
|
||
- `reconcile`
|
||
- 主要副作用:
|
||
- 写 HTTP Header 和 Body
|
||
- 错误/边界条件:
|
||
- JSON 编码错误被忽略,调用方不会收到显式错误
|
||
|
||
## 接口设计说明
|
||
|
||
- `collect-and-rate` 和 `reconcile` 在当前实现中只有作业名不同,没有独立 reconciliation 流程
|
||
- `/healthz` 反映的是最近一次作业的结果,不是即时数据库探活
|
||
- `/api/ping` 用于发布追踪,不依赖数据库或 exporter
|