go-zero 极简 HTTP header 解析
go-zero
对 REST 接口支持头部(Header)参数自动解析。这一特性增强了 API 设计的便捷性,使开发者可以更方便地从 HTTP 请求头中提取参数,并将其绑定到业务逻辑中。
本篇文章将以多租户(Multi-Tenant)系统为例,展示如何利用该特性简化 API 设计。
问题:多租户系统中的 Tenant ID 解析
在 SaaS(Software as a Service)架构中,通常一个系统需要支持多个租户,每个租户(Tenant)对应一个独立的业务实体,例如:
- 企业应用:不同公司用户共享一个系统,但数据是隔离的。
- 电商平台:商家有独立的后台管理系统,访问各自的数据。
- 云服务:不同用户租用同一个服务,但权限和资源需要隔离。
在这些场景下,常见的方式是通过 HTTP 头部 X-Tenant-Id
传递租户信息,例如:
GET /api/orders HTTP/1.1
X-Tenant-Id: tenant-123
传统做法需要在 handler 中手动解析 X-Tenant-Id
,但在 go-zero 的新特性支持下,可以通过声明式的方式自动解析 Header 参数。
示例:多租户 API 设计
1. 在 .api
文件中定义 API
在 go-zero 的 API 规范中,我们可以直接声明 HTTP 头部参数:
type OrderRequest {
TenantId string `header:"X-Tenant-Id"`
}
type OrderResponse {
Orders []string
}
@server (
prefix: "/api"
)
service order {
@handler GetOrders
get /orders (OrderRequest) returns (OrderResponse)
}
这样,go-zero 会自动解析 HTTP 请求头 X-Tenant-Id
并填充到 OrderRequest
结构体中。
2. 在 Handler 中使用
在生成的 logic
代码中,我们可以直接使用 TenantId
进行业务逻辑处理,例如:
func (l *GetOrdersLogic) GetOrders(req *types.OrderRequest) (resp *types.OrderResponse, err error) {
// 通过租户 ID 获取该租户的订单数据
orders := fetchOrdersForTenant(req.TenantId)
return &types.OrderResponse{Orders: orders}, nil
}
func fetchOrdersForTenant(tenantId string) []string {
// 模拟不同租户的订单数据
mockData := map[string][]string{
"tenant-123": {"Order A", "Order B"},
"tenant-456": {"Order X", "Order Y", "Order Z"},
}
return mockData[tenantId]
}
自动解析 HTTP header 的好处
1. 代码更简洁
以前需要手动解析 Header:
tenantId := r.Header.Get("X-Tenant-Id")
if tenantId == "" {
http.Error(w, "missing tenant ID", http.StatusBadRequest)
return
}
现在只需声明 header:"X-Tenant-Id"
,go-zero 自动完成解析。
2. 避免重复解析
如果多个 API 需要 X-Tenant-Id
,以前的做法是每个 handler 里都要 r.Header.Get("X-Tenant-Id")
,现在可以直接在 Request
结构体中定义,所有 handler 复用解析逻辑。
3. 强类型支持
以前 r.Header.Get()
返回 string
,需要手动转换类型,现在 go-zero 直接解析为 int
、bool
等类型,减少转换代码。
4. 提高可读性
API 结构清晰,开发者可以一眼看出 API 依赖哪些头部参数,而无需阅读 handler 代码。
示例请求与返回
如果客户端发送如下 HTTP 请求:
curl -H "X-Tenant-Id: tenant-123" http://localhost:8888/api/orders
服务端返回:
{"Orders":["Order A","Order B"]}
如果 X-Tenant-Id
头部缺失,返回错误:
field "X-Tenant-Id" is not set
结语
这个特性让 go-zero 的 REST API 设计更加直观、优雅,减少了手动解析 HTTP 头部的重复代码。它特别适用于多租户系统、用户标识传递、版本控制(X-API-Version
)、语言偏好(Accept-Language
)等场景。
本作品采用《CC 协议》,转载必须注明作者和本文链接