
本文介绍如何通过配置 http.Client.CheckRedirect 字段,让 Go 的 HTTP 客户端停止自动跟随 3xx 重定向,从而获取首次请求的完整响应(如 302 状态码、Header 和 Cookie),同时保持 Cookie 支持能力。
本文介绍如何通过配置 `http.client.checkredirect` 字段,让 go 的 http 客户端停止自动跟随 3xx 重定向,从而获取首次请求的完整响应(如 302 状态码、header 和 cookie),同时保持 cookie 支持能力。
在 Go 的 net/http 包中,http.Client 默认会自动处理 HTTP 重定向(如 301、302、307 等),最多跟随 10 次跳转,并返回最终响应。但某些场景下——例如调试认证流程、分析登录跳转逻辑、或需要显式读取 Location 头与 Set-Cookie ——我们必须阻止自动重定向,直接获取首次响应。
关键在于 http.Client 的 CheckRedirect 字段:它是一个类型为 func(*http.Request, []*http.Request) error 的回调函数。每当客户端准备执行重定向时,会调用该函数;若函数返回非 nil 错误,重定向即被中止,且客户端将返回上一次请求的响应(注意:此时响应 Body 仍处于打开状态,可读取)。
✅ 正确做法是返回 http.ErrUseLastResponse:
这是 Go 标准库预定义的特殊错误,明确指示客户端立即终止重定向,并返回当前(即重定向前)的响应对象,且不关闭其 Body,便于后续读取内容、解析 Header 或提取 Cookie。
以下是完整示例:
package main
import (
"fmt"
"io"
"log"
"net/http"
"net/http/cookiejar"
"net/url"
)
func main() {
// 创建支持 Cookie 的客户端(自动管理 cookie jar)
jar, _ := cookiejar.New(nil)
client := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse // 关键:禁用重定向,返回原始响应
},
Jar: jar,
}
resp, err := client.Get("https://httpbin.org/redirect-to?url=/cookies")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
fmt.Printf("Status Code: %d\n", resp.StatusCode) // 输出 302
fmt.Printf("Location Header: %s\n", resp.Header.Get("Location"))
// 读取响应体(可选,用于调试)
body, _ := io.ReadAll(resp.Body)
fmt.Printf("Response Body: %s\n", string(body))
// 获取本次响应中服务器设置的 Cookie(自动存入 jar)
cookies := jar.Cookies(&url.URL{Scheme: "https", Host: "httpbin.org"})
fmt.Printf("Cookies received: %+v\n", cookies)
}
⚠️ 注意事项:
- CheckRedirect 返回任意非 nil 错误都会中断重定向,但只有 http.ErrUseLastResponse 能保证返回未关闭的 resp.Body;其他错误(如 errors.New("stop"))会导致 resp 为 nil,仅返回错误。
- 若需手动管理 Cookie(而非依赖 Jar),可通过 resp.Header["Set-Cookie"] 解析并保存。
- CheckRedirect 不影响请求发起前的 Cookie 自动注入(只要设置了 Client.Jar),因此重定向前的请求仍携带已有 Cookie。
- 如需对特定重定向行为做细粒度控制(例如只禁止 302、允许 307),可在回调中检查 via[0].Response.StatusCode 并按需返回 http.ErrUseLastResponse 或其他错误。
总结:禁用 Go HTTP 客户端重定向的核心是正确使用 CheckRedirect + http.ErrUseLastResponse,配合 cookiejar 即可兼顾“获取原始响应”与“自动处理 Cookie”两大需求,无需绕行底层 RoundTrip,简洁、安全、符合标准实践。











