
在 Go 中,可通过设置 http.Client 的 CheckRedirect 字段为返回 http.ErrUseLastResponse 的函数,来禁用自动重定向,从而获取 302 等重定向状态码的原始响应体及 Cookie。
在 go 中,可通过设置 `http.client` 的 `checkredirect` 字段为返回 `http.erruselastresponse` 的函数,来禁用自动重定向,从而获取 302 等重定向状态码的原始响应体及 cookie。
默认情况下,Go 的 http.Client 会自动跟随 HTTP 重定向(如 301、302、307),直接返回最终响应,中间跳转过程被隐藏,且原始响应头(含 Set-Cookie)无法访问。但许多场景——例如实现登录流程调试、OAuth 授权码捕获、或需显式处理跳转逻辑时——要求客户端停止跟随重定向,并完整暴露首次响应(包括状态码、Header、Body 和 Cookies)。
解决方案是自定义 CheckRedirect 函数:该函数在每次重定向前被调用,若返回非 nil 错误,则终止重定向流程。关键在于——不要返回任意自定义错误(这会导致请求失败),而应返回 Go 标准库预定义的 http.ErrUseLastResponse。该错误指示客户端立即返回当前(即重定向前的)响应,且保持响应体 Body 未关闭,便于后续读取。
以下是一个完整、可运行的示例:
package main
import (
"fmt"
"io"
"net/http"
"net/http/cookiejar"
"strings"
)
func main() {
// 创建支持 Cookie 的客户端(可选,如需自动管理 Cookie)
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=/headers&status_code=302")
if err != nil {
panic(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))
// 获取 Set-Cookie(如有)
for _, cookie := range resp.Cookies() {
fmt.Printf("Received Cookie: %s=%s\n", cookie.Name, cookie.Value)
}
}✅ 注意事项:
- http.ErrUseLastResponse 是唯一安全、标准的方式实现“停止重定向并返回当前响应”;返回其他错误(如 errors.New("stop"))将导致 client.Do() 返回该错误,resp 为 nil。
- 若需手动管理 Cookie(而非依赖 Jar),可直接从 resp.Header["Set-Cookie"] 解析;启用 Jar 后,后续请求会自动携带服务端下发的 Cookie。
- CheckRedirect 不影响请求本身是否成功——它仅控制重定向行为;网络错误、超时等仍需通过 Client.Timeout 或 context 控制。
总之,通过一行关键配置 CheckRedirect: func(...) error { return http.ErrUseLastResponse },即可让 http.Client 行为符合 RESTful 调试与协议交互的真实需求:透明、可控、可审计。


















