必须用 app.use 注册,因其对所有 http 方法生效且支持路径前缀匹配(如 "/" 匹配全部请求),而 app.get 等仅限特定方法,无法实现协议层统一跳转;需优先检查 x-forwarded-proto 判断 https,再 fallback 到 c.protocol();跳转时必须 return c.redirect() 终止流程,严禁 c.next() 导致响应冲突。

必须用 app.Use 注册,不能用 app.Get 或其他方法;跳转逻辑需手动判断协议并调用 c.Redirect,且绝不能调 c.Next() —— 否则会继续执行后续 handler,导致响应冲突或 panic。
为什么 app.Use 是唯一正确入口
Fiber 的 app.Use 对所有 HTTP 方法生效(GET/POST/PUT/DELETE 等),而强制跳转 HTTPS 是协议层统一行为,不应只覆盖 GET。若误用 app.Get("/", ...),POST 请求仍走 HTTP,失去防护意义。源码中 methodUse 会把路由复制到全部 app.config.RequestMethods 栈,这是设计保障。
-
app.Use的前缀匹配是路径前缀语义:传"/"会匹配所有请求,包括/api/users、/static/logo.png - 传空字符串
""或"/"效果一致,但显式写"/"更可读 - 不能用
app.All替代 —— 它注册的是终结点(handler),不是中间件,无法在路由分发前介入
c.Protocol() 判断不靠谱,得看 X-Forwarded-Proto 和 c.Host
Fiber 的 c.Protocol() 返回的是原始请求的 scheme(通常是 http),哪怕你用 Nginx 反向代理并设置了 X-Forwarded-Proto: https,它也不会自动识别。真正可靠的判断顺序是:
- 优先检查
c.Get("X-Forwarded-Proto") == "https"(适用于反代场景) - fallback 到
c.Protocol() == "https"(仅限直连开发环境) - 若两者都不满足,再检查
c.Host()是否含端口:443(辅助判断,不推荐依赖)
漏掉 X-Forwarded-Proto 是生产环境最常见翻车点 —— 所有云服务(AWS ALB、Cloudflare、Nginx)都靠它传递真实协议。
跳转时必须终止流程,禁止调用 c.Next()
一旦决定跳转,就要立刻返回错误或直接结束响应,否则 c.Next() 会让请求继续进入后续中间件或路由 handler,轻则重复写 header 导致 http: multiple response.WriteHeader calls panic,重则泄露未授权内容。
- 正确写法:
return c.Redirect("https://" + c.Host() + c.OriginalURL(), 301) - 错误写法:
c.Redirect(...); c.Next()—— 绝对禁止 - 更安全的写法:加
return nil显式退出,避免被后续代码干扰
注意 c.OriginalURL() 保留完整 path + query,比拼接 c.Path() + c.Queries() 更可靠,尤其含特殊字符时。
本地开发要不要跳转?用环境变量控制最稳妥
硬编码跳转会卡死本地 http://localhost:3000 调试。建议用 os.Getenv("ENV") == "production" 或类似开关包裹逻辑:
app.Use(func(c *fiber.Ctx) error {
if os.Getenv("ENV") != "production" {
return c.Next()
}
if c.Get("X-Forwarded-Proto") != "https" && c.Protocol() != "https" {
return c.Redirect("https://" + c.Host() + c.OriginalURL(), 301)
}
return c.Next()
})
这个分支结构容易被忽略:跳转逻辑只在生产环境生效,且只对非 HTTPS 请求触发 —— 其他情况一律放行。少一个条件,就可能造成循环重定向或拦截合法请求。











