Buffalo 不提供 req.Protocol 是因 Go net/http 的 *http.Request 本身无该字段;判断 HTTP/HTTPS 应优先检查 X-Forwarded-Proto 头,其次 fallback 到 req.TLS != nil;需在中间件中统一注入 scheme 并确保代理正确设置该头。

Buffalo 框架里不能直接靠 req.Protocol 或类似字段获取协议类型,它压根没提供这个属性 —— 你得从 req.URL.Scheme 或 req.Header 里推导。
为什么 Buffalo 不暴露 req.Protocol?
Buffalo 基于 Go 的 net/http,而标准库的 *http.Request 本身就没有 Protocol 字段(比如 "HTTP/1.1" 或 "HTTP/2")。它只在底层连接建立时由服务器决定,Request 对象只保留解析后的请求行信息,不反向暴露协议版本。
常见误区是以为 req.Proto 就是“协议类型”,但它实际是字符串如 "HTTP/1.1",且不可靠:代理转发、TLS 终止、负载均衡器重写后,req.Proto 可能仍是 "HTTP/1.1",哪怕客户端用的是 HTTP/2。
-
req.Proto是原始请求行中解析出的协议标识,不是运行时真实协商的协议 - 真实协议信息(如是否为 HTTP/2)藏在
http.Server的底层连接中,Buffalo 未做透传 - 绝大多数业务场景真正关心的是“是否 HTTPS”,而不是 HTTP/1.1 还是 HTTP/2
怎么判断当前请求是 HTTP 还是 HTTPS?
最稳妥的方式是检查 req.URL.Scheme,但注意:它默认总是 "http",除非你手动设置或通过中间件修正。Buffalo 默认不自动填充 Scheme,尤其在反向代理后容易出错。
Buffalo框架 1.0.1 版本源码包下载,适合需要错误处理改进、依赖更新、render.Download 注释和 request logger 调整的 v1 项目。
推荐做法是结合 X-Forwarded-Proto 头(Nginx / Traefik / Cloudflare 等常用):
func GetScheme(c buffalo.Context) string {
req := c.Request()
scheme := req.Header.Get("X-Forwarded-Proto")
if scheme == "https" || scheme == "HTTP/2" {
return "https"
}
// fallback:检查 TLS 状态(适用于直连,无代理场景)
if req.TLS != nil {
return "https"
}
return "http"
}
- 必须确保反向代理配置了
proxy_set_header X-Forwarded-Proto $scheme;(Nginx)或等效项 - 若未启用代理,
req.TLS != nil是更可靠的 HTTPS 判断依据 - 不要依赖
req.URL.Scheme的初始值 —— 它在代理后通常仍是"http"
如何在中间件中统一注入正确 Scheme?
Buffalo 支持全局中间件,适合一次性修正请求上下文。把 Scheme 注入到 c.Data 或自定义 context key,避免每个 handler 重复判断:
app.Use(func(next buffalo.Handler) buffalo.Handler {
return func(c buffalo.Context) error {
req := c.Request()
scheme := "http"
if forwarded := req.Header.Get("X-Forwarded-Proto"); forwarded == "https" {
scheme = "https"
} else if req.TLS != nil {
scheme = "https"
}
c.Set("scheme", scheme)
return next(c)
}
})
- 后续 handler 中可用
c.Param("scheme")或c.Data["scheme"]获取 - 若使用 HTTPS 重定向逻辑,应基于此
scheme值判断,而非硬编码或猜 - 注意:某些 CDN(如 Cloudflare)可能用
X-Forwarded-Ssl: on替代X-Forwarded-Proto,需按实际调整
真正难的不是取值,而是确认你拿到的是代理链末端的真实协议 —— 如果漏配 X-Forwarded-Proto 或信任了伪造头,scheme 就会彻底失真。别跳过验证代理配置这步。

















