fiber 无法直接反向代理,必须用 httputil.newsinglehostreverseproxy 手动转发:需重写 url scheme/host/path、剥离前缀、禁用 bodyparser 等干扰中间件,并配置 transport 控制连接与超时。

Fiber 本身不提供反向代理能力,app.Get("/api/*", ...) 这类路由写法只是匹配路径,不能自动转发请求——必须手动集成 httputil.NewSingleHostReverseProxy 或可靠 HTTP 客户端,并绕过 Fiber 中间件干扰。
为什么不能直接在 Fiber 路由里用 http.DefaultClient.Do
常见错误是把 c.Body() 直接塞进新 http.Request,结果转发时 Body 为空、Header 丢失、连接爆炸:
-
http.Request.Body只能读一次,c.Body()已被 Fiber 解析过,再读就是空字节流 - Fiber 默认不透传
Authorization、Cookie、Content-Type等关键 Header,需手动拷贝 -
http.DefaultClient.Transport.MaxIdleConnsPerHost默认为 2,压测几秒就触发dial tcp: too many open files - 无法处理
Transfer-Encoding: chunked或流式响应(如 SSE、大文件下载),io.Copy易卡死或截断
正确做法:Fiber 做路由+限流,httputil.ReverseProxy 做转发
把 Fiber 当成“智能前置”,只负责路径匹配、鉴权、打标、限流;真实转发交给标准库的 httputil.NewSingleHostReverseProxy:
安装并运行 Aperture(Lightning Labs 的 L402 闪电反向代理),用于创建 L402 付费墙、配置付费 API 端点、为其他代理托管付费内容或测试 L402 认证流程。
- 每个后端配独立
*httputil.ReverseProxy实例,显式设置Director和自定义Transport -
Director必须重写req.URL.Scheme、req.URL.Host、req.URL.Path,漏一项就发错地址 - 用
http.StripPrefix剥离前缀(如/api/),避免后端收到带前缀的路径 - 路由 handler 里直接调用
proxy.ServeHTTP(c.Fasthttp.Response, c.Fasthttp.Request),不要走c.Next()或中间件链
必须关闭的 Fiber 中间件
代理路由不能启用会提前消费 Body 或篡改 Header 的中间件:
- 禁用
BodyParser:它会调用c.Body(),导致转发时 Body 为空 - 禁用默认
Logger(除非你重写了日志逻辑):它可能修改Content-Length或提前写响应头 - 限流放路由层(如
fiber.AdvanceRateLimiter),别塞进Director函数里——那里没上下文生命周期控制 - 若需鉴权,应在
proxy.ServeHTTP调用前完成,并把 token 注入req.Header.Set("Authorization", token)
Transport 层才是真正的流控底座
fiber.RateLimit 只管请求数,对长连接、大文件、后端 hang 住完全无效。真实流控必须落在连接和响应读取维度:
- 设
MaxIdleConnsPerHost: 100和IdleConnTimeout: 30 * time.Second,防止 fd 耗尽 -
ReadTimeout控制响应体读取超时,能中断卡死的 goroutine;ResponseHeaderTimeout控制握手阶段等待 - 不要用
context.WithTimeout包裹proxy.ServeHTTP——它不中断底层 TCP 流,超时必须由Transport触发 - 若对接多个上游(如
api.example.com和auth.example.com),用fasthttp.HostClient替代全局http.Client,避免 Host 头错乱或 TLS SNI 冲突
最易被忽略的是 Director 函数里没设 req.URL.Scheme 和 req.URL.Host,尤其后端是 HTTPS 时,默认仍用 http 协议发起连接,结果就是 TLS 握手失败或 502;还有人把 proxy.ServeHTTP 放在 ctx.Next() 后面,导致日志中间件已写 header,转发再写就 panic。










