Gin 本身不处理反向代理,真正执行反向代理的是 Nginx;应让 Nginx 监听 80/443 端口并 proxy_pass 到 Gin 的 127.0.0.1:8080,同时必须配置 Host、X-Real-IP、X-Forwarded-For 及 WebSocket 相关头,否则将出现 502、400、CORS 或 IP 识别错误等问题。

直接上结论:Gin 本身不处理反向代理,它只负责业务逻辑;Nginx 才是真正做反向代理的组件。你不需要在 Gin 里写代理逻辑,而是让 Nginx 监听 80/443 端口,把请求转发给运行在本地(如 127.0.0.1:8080)的 Gin 进程——这是最稳定、最常用、也最符合生产规范的做法。
为什么 Gin 不该自己做反向代理?
虽然有 github.com/go-dev-frame/sponge/pkg/gin/proxy 这类库能让你在 Gin 中嵌入代理能力,但它本质是用 net/http/httputil.NewSingleHostReverseProxy 封装的,属于“网关+业务混跑”模式。这在调试或小规模灰度时可行,但会带来几个硬伤:
- 健康检查、连接池、SSL 终端、HTTP/2 支持、缓冲控制等都得自己补全,而 Nginx 原生就支持且久经考验
- Gin 进程一旦挂掉,代理和业务同时不可用;Nginx 是独立进程,稳定性高得多
- 无法复用 Nginx 的缓存、限流、WAF 规则、日志格式等运维能力
-
proxy_pass路径改写、X-Forwarded-For注入、Host头透传这些细节,Nginx 配置一行搞定,Go 里容易漏掉
Nginx 配置 proxy_pass 到 Gin 的关键点
假设你的 Gin 应用监听 127.0.0.1:8080,Nginx 需要把它暴露成公网域名(比如 api.example.com)。核心配置不是写死 proxy_pass http://127.0.0.1:8080 就完事,要注意以下几处:
- 必须加
proxy_set_header Host $host;,否则 Gin 的c.Request.Host会变成127.0.0.1:8080,影响 CORS、重定向、生成绝对 URL 等逻辑 - 务必设置
proxy_set_header X-Real-IP $remote_addr;和proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;,否则 Gin 拿不到真实客户端 IP - 如果 Gin 使用了 WebSocket(比如
/ws),需额外加proxy_http_version 1.1;和proxy_set_header Upgrade $http_upgrade;,否则握手失败 -
proxy_pass末尾带斜杠(proxy_pass http://backend/;)会截断匹配的location路径;不带斜杠(proxy_pass http://backend;)则原样拼接,这点极易出错
常见错误现象与对应配置修正
部署后发现接口 502、400、CORS 报错或 IP 记录为 127.0.0.1,大概率是下面某条没配对:
-
502 Bad Gateway:Gin 进程没起来,或 Nginx 无法连通127.0.0.1:8080;检查netstat -tuln | grep :8080和curl -v http://127.0.0.1:8080/ping -
400 Bad Request(尤其 WebSocket):缺proxy_http_version 1.1;或Upgrade头;补上即可 - CORS 报错说
Origin not allowed:Gin 里用了c.Header("Access-Control-Allow-Origin", "*"),但前端发的是带凭证的请求(withCredentials: true),此时不能用*,得动态回写Origin头——而这个值必须从 Nginx 透传过来,所以proxy_set_header Origin $http_origin;得加上 - 日志里所有
RemoteAddr都是127.0.0.1:漏了X-Real-IP和X-Forwarded-For设置,Gin 的c.ClientIP()就失效了
真正难的不是写配置,而是确认每一层头信息是否按预期传递——Nginx 是透明的中间人,它不修改请求语义,但如果你没显式透传,Gin 就永远看不到原始上下文。











