应使用 X-Forwarded-Proto 头判断 HTTPS:优先取 c.Request().Header.Get("X-Forwarded-Proto") 并转小写比对 "https",缺失时 fallback 到 c.Request().TLS != nil;不可依赖 c.Request().URL.Scheme。

Context.Request().URL.Scheme 在 Echo 中不可靠
直接读 c.Request().URL.Scheme 得到的值通常是 "http",哪怕请求实际走的是 HTTPS。这是因为反向代理(如 Nginx、Cloudflare)转发时,原始 TLS 信息不会自动透传到 Go 的 *http.Request 结构体里;URL.Scheme 是由 Go HTTP Server 自己根据监听协议推断的,不反映客户端真实协议。
正确识别 HTTPS 应该检查 X-Forwarded-Proto 头
当服务部署在反向代理后,必须依赖代理注入的标准头字段。最通用、最可靠的方式是读取 X-Forwarded-Proto:
- 若代理配置了
proxy_set_header X-Forwarded-Proto $scheme;(Nginx),或等效设置(如 Traefik 的forwardedHeaders.insecure),该头值就是原始协议 - 优先使用
c.Request().Header.Get("X-Forwarded-Proto"),而非c.Request().URL.Scheme - 需做空值和大小写处理:
strings.ToLower()后比对"https" - 若未启用代理或头缺失,再 fallback 到
c.Request().TLS != nil(仅适用于直连 HTTPS 场景)
RealIP 中间件会影响 Scheme 判断逻辑
Echo v5.1.0 起 middleware.RealIP() 默认启用 X-Forwarded-For 解析,但它**不自动处理 X-Forwarded-Proto**。你不能指望调用了 RealIP() 就能安全读 X-Forwarded-Proto —— 它只是帮你修正了客户端 IP,协议头仍需手动提取。
常见错误写法:
Echo框架 5.1.0 版本源码包下载,适合关注 RealIP 行为变化、StartConfig.Listener、NewDefaultFS 和观测性中间件入口的开发团队。
e.Use(middleware.RealIP()) // 后续直接用 c.Request().URL.Scheme —— 依然错
正确组合应是:
- 确保代理已透传
X-Forwarded-Proto - 在 handler 或中间件中显式读取并校验该头
- 必要时封装一个
IsSecure(c echo.Context) bool工具函数,统一处理 fallback 逻辑
不要在路由匹配或中间件跳转中依赖 Scheme 做硬判断
比如写 if c.Request().URL.Scheme == "https" { ... } 做重定向,大概率在生产环境失效。HTTPS 重定向中间件(如 middleware.HTTPSRedirect())内部其实也是基于 X-Forwarded-Proto + Request.Host 构造跳转 URL 的。
真正要做的只有两件事:
- 确认你的反向代理配置了
X-Forwarded-Proto - 所有业务逻辑中判断协议的地方,全部替换为
strings.EqualFold(c.Request().Header.Get("X-Forwarded-Proto"), "https")
漏掉大小写处理或忽略代理头缺失的 fallback,是线上环境最常被忽略的细节。
















