http 302 重定向后客户端不带原始请求 cookie,因浏览器发起新 get 请求且不复用旧请求头;需手动透传、同源保障或编码状态到 url。

HTTP 302 重定向后客户端不带 Cookie?
默认 http.Redirect 不会保留原始请求的 Cookie,因为它是服务端发起的新响应,不自动转发请求头。浏览器收到 302 后用 GET 重新请求新地址,但旧请求里的 Cookie 头不会被复用——除非你手动透传或依赖客户端已有域内 Cookie。
常见错误现象:Set-Cookie 在重定向前已写入响应,但跳转后登录态丢失、Session 看似“没生效”。
- 如果要透传认证信息,别依赖重定向自动带 Cookie;改用服务端内部跳转(如
http.ServeFile或模板渲染),或把必要状态编码进重定向 URL(如?token=xxx) - 确保重定向目标域名和原始请求一致(同源),否则浏览器根本不会发送对应域的 Cookie
-
http.Redirect的第四个参数是状态码,别误传http.StatusFound(302)以外的值,比如写成301会导致浏览器缓存重定向,后续修改逻辑也不生效
用 http.Redirect 时 Location 头不合法?
http.Redirect 要求 url 参数必须是绝对路径或完整 URL,相对路径会触发 panic 或返回 500,错误信息类似:http: invalid pattern 或直接 panic: malformed URL。
使用场景:从 API 路由(如 /login)跳转到前端页面(如 /dashboard),但硬写 "../dashboard" 就挂了。
立即学习“go语言免费学习笔记(深入)”;
- 永远用
url.JoinPath(r.URL.Scheme+"://"+r.Host, "/dashboard")拼接,或更稳妥地用url.URL{Scheme: "https", Host: r.Host, Path: "/dashboard"}.String() - 别在生产环境拼接字符串构造 URL,
r.Host可能被恶意篡改,需白名单校验或统一用配置项 - 如果重定向目标是外部地址(如 OAuth 回调),务必对
url做有效性检查,避免开放重定向漏洞(Open Redirect)
重定向循环:302 → 302 → … 最终报 ERR_TOO_MANY_REDIRECTS
Golang 本身不限制重定向次数,但浏览器通常在 20 次左右中断并报错。问题往往出在重定向逻辑没做守卫条件,比如未校验用户是否已登录,就无脑跳回登录页。
典型错误代码:if !isAuthenticated(r) { http.Redirect(w, r, "/login", http.StatusFound); return } —— 但 /login 路由自己又执行了同样判断,没放行。
- 所有重定向入口都得有明确退出路径,比如
/login路由必须允许未登录用户访问,且不重定向自己 - 加日志:在重定向前打一行
log.Printf("redirecting %s → %s", r.RequestURI, target),本地调试时一眼看出循环链 - 别用中间件全局拦截并重定向,除非你能精确控制路径匹配逻辑(比如排除
/login、/static/等免检路径)
http.Redirect 和 http.Error 混用导致 header 已写入?
一旦调用 http.Redirect 或 http.Error,Go 就会向响应体写入内容并设置 Content-Type 和状态码。之后再调用任何写响应的操作(包括再次 http.Redirect)都会 panic:http: multiple response.WriteHeader calls。
性能影响不大,但会导致整个请求崩溃,错误堆栈藏在服务日志里,不容易定位。
- 每个 HTTP handler 函数里,
http.Redirect或http.Error后必须紧跟return,不能漏 - 别在 if-else 之外写重定向逻辑,比如把
http.Redirect放在 defer 里——defer 执行时 header 很可能已被写过 - 用
if err != nil { http.Error(w, err.Error(), http.StatusBadRequest); return }这类模式,确保错误出口干净
重定向看着简单,真正卡住人的往往是 Cookie 生效边界、URL 构造合法性、以及多层中间件下控制流的隐式耦合。这些地方不写测试,上线后只能靠日志反复猜。










