直接用 httputil.newsinglehostreverseproxy 会丢 header,因为它默认清理 x-forwarded-for、authorization 等“不安全”字段;必须重写 director 显式透传关键 header(如 x-forwarded-for、authorization、x-gray-id),并设置 req.url.scheme、req.host 和 req.url.path,否则下游鉴权、路由和真实 ip 获取全部失效。

为什么直接用 httputil.NewSingleHostReverseProxy 会丢 Header
Go 标准库的 ReverseProxy 默认会清理部分上游 Header,比如 X-Forwarded-For、X-Real-IP、Authorization 等——它认为这些是“不安全”或“可能被伪造”的字段,会在转发前主动删除。
现象:Nginx 已配 proxy_set_header X-Gray-ID $http_x_gray_id,但 Gin 代理层收不到该 Header;或者下游服务看到 Host 变成代理目标地址而非原始域名。
- 必须显式重写
Director函数,在其中手动恢复关键 Header -
c.Request.Header是原始请求头副本,可直接读取;但转发时需赋给req.Header(即proxy.Director参数中的req) - 不要依赖
proxy.Transport或中间件自动透传——Director是唯一可靠入口点
Director 函数里必须重写的三项关键字段
Director 不只是改 req.URL,漏掉以下任一都会导致下游服务行为异常:
-
req.URL.Scheme = "https"(或与目标一致),否则 HTTP/HTTPS 混合场景下 TLS 握手失败 -
req.Host = targetHost(不是req.URL.Host),某些网关(如 Cloudflare、Envoy)只认 Host header 做路由 -
req.Header.Set("X-Forwarded-For", c.ClientIP()),否则下游无法获取真实客户端 IP
示例片段:
proxy.Director = func(req *http.Request) {
req.URL.Scheme = url.Scheme
req.URL.Host = url.Host
req.Host = url.Host // 关键:覆盖 Host header
req.Header.Set("X-Forwarded-For", c.ClientIP())
req.Header.Set("X-Gray-ID", c.GetHeader("X-Gray-ID")) // 显式透传灰度标识
}
多级代理时如何避免 X-Forwarded-For 重复追加
若请求已过 Nginx → Gin 代理 A → Gin 代理 B → 后端,每层都无脑 Set("X-Forwarded-For", ip),会导致 header 值变成 1.1.1.1, 2.2.2.2, 2.2.2.2(重复)。
- 正确做法是先
Get("X-Forwarded-For"),若非空则拼接:c.ClientIP() + ", " + existing - 但注意:Gin 的
c.ClientIP()在有前置 Nginx 时需确保Trusted IPs已配置,否则返回的是 Nginx IP 而非真实客户端 - 更稳妥的方式是直接从
c.Request.Header.Get("X-Real-IP")读取——前提是 Nginx 已设proxy_set_header X-Real-IP $remote_addr
透传 Cookie 和认证 Header 的边界条件
Authorization、Cookie 这类敏感 Header,默认被 ReverseProxy 屏蔽,且不会出现在 c.Request.Header 中(除非显式开启)。
- 必须在
Director中手动复制:req.Header.Set("Authorization", c.GetHeader("Authorization")) - Cookie 需注意路径和域:若后端服务要求
Domain=example.com,而代理层在api.example.com,需在Director中解析并重写Cookieheader 字符串(不能直接 Set) - 对
Set-Cookie响应头的处理更复杂——ReverseProxy不提供响应修改钩子,需自定义ModifyResponse函数
真正难的不是写透传逻辑,而是厘清每一层代理该信任谁、该保留什么、该剥离什么。Header 一旦错传,下游鉴权或路由就全乱了。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











