代理功能
Zoox 提供了强大的代理功能,支持反向代理、路径重写和请求/响应钩子。
基本用法
简单代理
go
package main
import "github.com/go-zoox/zoox"
func main() {
app := zoox.New()
// 将 /api 路径的请求代理到后端服务
app.Proxy("/api", "http://backend:8080")
app.Run(":8080")
}说明: 代理实现参考 group.go:145-192。
路径重写
基本重写
go
app.Proxy("/api/v1", "http://backend:8080", func(cfg *zoox.ProxyConfig) {
cfg.Rewrites = []zoox.Rewrite{
{From: "/api/v1/(.*)", To: "/$1"},
}
})访问 /api/v1/users 会被重写为 /users 并代理到后端。
多个重写规则
go
app.Proxy("/api", "http://backend:8080", func(cfg *zoox.ProxyConfig) {
cfg.Rewrites = []zoox.Rewrite{
{From: "/api/v1/(.*)", To: "/v1/$1"},
{From: "/api/v2/(.*)", To: "/v2/$1"},
}
})请求/响应钩子
OnRequestWithContext
在请求发送到后端前执行:
go
app.Proxy("/api", "http://backend:8080", func(cfg *zoox.ProxyConfig) {
cfg.OnRequestWithContext = func(ctx *zoox.Context) error {
// 添加请求头
ctx.SetHeader("X-Forwarded-For", ctx.IP())
ctx.SetHeader("X-Request-ID", ctx.RequestID())
// 修改请求路径
// ctx.Request.URL.Path = "/new-path"
return nil
}
})OnResponseWithContext
在响应返回给客户端前执行:
go
app.Proxy("/api", "http://backend:8080", func(cfg *zoox.ProxyConfig) {
cfg.OnResponseWithContext = func(ctx *zoox.Context) error {
// 修改响应头
ctx.SetHeader("X-Proxy-By", "zoox")
// 记录响应
ctx.Logger.Infof("Proxied response: %d", ctx.StatusCode())
return nil
}
})完整示例
go
package main
import (
"github.com/go-zoox/zoox"
"github.com/go-zoox/zoox/middleware"
)
func main() {
app := zoox.New()
// 全局中间件
app.Use(middleware.Logger())
app.Use(middleware.Recovery())
// 代理配置
app.Proxy("/api", "http://backend:8080", func(cfg *zoox.ProxyConfig) {
// 路径重写
cfg.Rewrites = []zoox.Rewrite{
{From: "/api/(.*)", To: "/$1"},
}
// 请求钩子
cfg.OnRequestWithContext = func(ctx *zoox.Context) error {
// 添加认证头
token := ctx.Header().Get("Authorization")
if token != "" {
ctx.SetHeader("X-Backend-Auth", token)
}
// 记录请求
ctx.Logger.Infof("Proxying request: %s %s", ctx.Method, ctx.Path)
return nil
}
// 响应钩子
cfg.OnResponseWithContext = func(ctx *zoox.Context) error {
// 添加响应头
ctx.SetHeader("X-Proxy-By", "zoox")
// 记录响应
ctx.Logger.Infof("Proxied response: %d", ctx.StatusCode())
return nil
}
})
app.Run(":8080")
}错误处理
代理过程中的错误处理:
go
app.Proxy("/api", "http://backend:8080", func(cfg *zoox.ProxyConfig) {
cfg.OnRequestWithContext = func(ctx *zoox.Context) error {
// 如果返回错误,代理请求会被取消
if someCondition {
return errors.New("request rejected")
}
return nil
}
cfg.OnResponseWithContext = func(ctx *zoox.Context) error {
// 如果返回错误,响应会被标记为错误
if ctx.StatusCode() >= 500 {
ctx.Logger.Errorf("Backend error: %d", ctx.StatusCode())
}
return nil
}
})负载均衡
虽然 Zoox 本身不提供负载均衡,但可以通过中间件实现:
go
type LoadBalancer struct {
backends []string
current int
mutex sync.Mutex
}
func (lb *LoadBalancer) Next() string {
lb.mutex.Lock()
defer lb.mutex.Unlock()
backend := lb.backends[lb.current]
lb.current = (lb.current + 1) % len(lb.backends)
return backend
}
func main() {
app := zoox.New()
lb := &LoadBalancer{
backends: []string{
"http://backend1:8080",
"http://backend2:8080",
"http://backend3:8080",
},
}
app.Proxy("/api", "", func(cfg *zoox.ProxyConfig) {
cfg.OnRequestWithContext = func(ctx *zoox.Context) error {
// 选择后端服务器
backend := lb.Next()
ctx.Request.URL.Host = backend
return nil
}
})
app.Run(":8080")
}使用中间件重写
也可以使用 Rewrite 中间件:
go
import "github.com/go-zoox/zoox/middleware"
app.Use(middleware.Rewrite(&middleware.RewriteConfig{
Rewrites: []middleware.Rewrite{
{From: "/api/v1/(.*)", To: "/$1"},
},
}))说明: Rewrite 中间件参考 middleware/rewrite.go。
最佳实践
1. 添加请求追踪
go
cfg.OnRequestWithContext = func(ctx *zoox.Context) error {
ctx.SetHeader("X-Request-ID", ctx.RequestID())
ctx.SetHeader("X-Forwarded-For", ctx.IP())
return nil
}2. 错误处理
go
cfg.OnResponseWithContext = func(ctx *zoox.Context) error {
if ctx.StatusCode() >= 500 {
// 记录错误
ctx.Logger.Errorf("Backend error: %d", ctx.StatusCode())
}
return nil
}3. 认证传递
go
cfg.OnRequestWithContext = func(ctx *zoox.Context) error {
// 传递认证信息
token := ctx.Header().Get("Authorization")
if token != "" {
ctx.SetHeader("X-Backend-Auth", token)
}
return nil
}下一步
需要更多帮助? 👉 完整文档索引
