fiber需用fiber.wraphandler桥接fasthttp.reverseproxy实现反向代理,不可直接用fiber.handler;必须显式配置hostclient超时、连接池及director路径重写,fiber仅作路由壳子。

用 fiber.Router 配合 fasthttp.ReverseProxy 实现反向代理
Fiber 本身不内置反向代理中间件,但底层基于 fasthttp,可以直接复用其 fasthttp.NewReverseProxy。关键不是“配 Fiber”,而是把 fasthttp.ReverseProxy 正确挂载到 Fiber 路由上。
常见错误是试图用 fiber.Handler 包裹 fasthttp.RequestHandler 时忽略类型转换——fasthttp.ReverseProxy 返回的是 fasthttp.RequestHandler,而 Fiber 的 Use/Get 等方法只接受 fiber.Handler。必须用 fiber.WrapHandler 桥接:
-
fiber.WrapHandler是唯一安全的包装方式,它会正确透传fasthttp.RequestCtx - 不要自己写闭包强制类型断言,会导致上下文丢失、
ctx.Send失效、日志错乱 - 目标地址必须带协议(如
http://backend:8080),否则fasthttp.NewReverseProxy会 panic
示例:
<pre class="brush:php;toolbar:false;">proxy := fasthttp.NewReverseProxy(&fasthttp.HostClient{
Addr: "backend:8080",
})
app.Get("/api/*", fiber.WrapHandler(proxy.ServeHTTP))
路径重写要用 fasthttp.ReverseProxy
的 Director 字段默认反向代理会原样转发路径,比如访问 /api/users,后端收到的也是 /api/users。如果后端只处理 /users,就得改路径——这不是 Fiber 的事,得在 ReverseProxy 层做。
Director 是一个函数,接收原始 *fasthttp.Request,允许你任意修改 RequestURI、Host、Header 等:
- 修改路径:用
req.URI().SetPath替换前缀,例如把/api/xxx→/xxx - 注意:不能直接改
req.RequestURI()字符串,那是只读副本;必须用URI().SetXxx方法 - 如果后端需要真实客户端 IP,记得手动设置
X-Forwarded-For:req.Header.Set("X-Forwarded-For", ctx.IP())
示例(去掉 /api 前缀):
<pre class="brush:php;toolbar:false;">proxy := fasthttp.NewReverseProxy(&fasthttp.HostClient{
Addr: "backend:8080",
})
proxy.Director = func(req *fasthttp.Request) {
path := string(req.URI().Path())
if strings.HasPrefix(path, "/api/") {
req.URI().SetPath(strings.TrimPrefix(path, "/api"))
}
req.Header.Set("X-Forwarded-For", string(req.Header.Peek("X-Real-IP")))
}
app.Get("/api/*", fiber.WrapHandler(proxy.ServeHTTP))
超时和连接池要显式配置 fasthttp.HostClient
默认 fasthttp.HostClient 的超时极短(3 秒),且无连接复用,在高并发或慢后端场景下极易触发 timeout error 或连接耗尽。Fiber 不参与这部分控制,必须在初始化 HostClient 时设好。
-
ReadTimeout和WriteTimeout至少设为 30s 起步,根据后端响应时间调整 -
MaxConnsPerHost默认是 512,流量大时需调高(如 2048) - 开启
DisableKeepAlive: false(默认就是 false),否则无法复用连接,性能暴跌 - 别漏掉
MaxIdleConnDuration,避免后端主动断连后 Fiber 还拿旧连接发请求
示例:
<pre class="brush:php;toolbar:false;">client := &fasthttp.HostClient{
Addr: "backend:8080",
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
MaxConnsPerHost: 2048,
MaxIdleConnDuration: 60 * time.Second,
DisableKeepAlive: false,
}
proxy := fasthttp.NewReverseProxy(client)
HTTPS 后端或 WebSocket 需额外处理 Upgrade
请求如果后端是 HTTPS,fasthttp.HostClient 无法直连(它不支持 TLS 服务发现),得用 fasthttp.LegacyClient + 自定义 Transport,或者更简单:让反向代理层(如 Nginx)处理 TLS 终结,Fiber 只走内网 HTTP。
WebSocket 更麻烦——fasthttp.ReverseProxy 默认不透传 Upgrade 请求头,必须手动放行:
- 检查
req.Header.Contains("Upgrade"),若为websocket,需设置req.Header.Set("Connection", "Upgrade") - 还要确保
HostClient允许升级:client.MaxConnsPerHost要足够,且不能设DisableKeepAlive: true - Fiber 的
WrapHandler对 WebSocket 是透明的,只要底层fasthttp支持即可
WebSocket 代理的关键几行:
<pre class="brush:php;toolbar:false;">proxy.Director = func(req *fasthttp.Request) {
if bytes.EqualFold(req.Header.Peek("Upgrade"), []byte("websocket")) {
req.Header.Set("Connection", "Upgrade")
req.Header.Set("Upgrade", "websocket")
}
// ... 其他路径/Host 修改
}
真正容易被忽略的点是:所有 fasthttp
HostClient 和 ReverseProxy 初始化逻辑,而不是翻 Fiber 文档。Fiber 在这里只是个轻量路由壳子。











