环境

go1.13.5

分析

net/httphttp

但是当我们需要获取重定向的相关信息的时候怎么办呢?

Client.Do

If the server replies with a redirect, the Client first uses the CheckRedirect function to determine whether the redirect should be followed. If permitted, a 301, 302, or 303 redirect causes subsequent requests to use HTTP method GET (or HEAD if the original request was HEAD), with no body. A 307 or 308 redirect preserves the original HTTP method and body, provided that the Request.GetBody function is defined. The NewRequest function automatically sets GetBody for common standard library body types.

CheckRedirect
forc.checkRedirectnilerror
errErrUseLastResponse
err = c.checkRedirect(req, reqs)

// Sentinel error to let users select the
// previous response, without closing its
// body. See Issue 10069.
if err == ErrUseLastResponse {
    return resp, nil
}

// ....省略

if err != nil {
    // Special case for Go 1 compatibility: return both the response
    // and an error if the CheckRedirect function failed.
    // See https://golang.org/issue/3795
    // The resp.Body has already been closed.
    ue := uerr(err)
    ue.(*url.Error).URL = loc
    return resp, ue
}
redirectBehavior3XXshouldRedirect
var shouldRedirect bool
redirectMethod, shouldRedirect, includeBody = redirectBehavior(req.Method, resp, reqs[0])
if !shouldRedirect {
    return resp, nil
}
c.checkRedirectc.CheckRedirectc.CheckRedirectnildefaultCheckRedirect
// checkRedirect calls either the user's configured CheckRedirect
// function, or the default.
func (c *Client) checkRedirect(req *Request, via []*Request) error {
	fn := c.CheckRedirect
	if fn == nil {
		fn = defaultCheckRedirect
	}
	return fn(req, via)
}

func defaultCheckRedirect(req *Request, via []*Request) error {
   if len(via) >= 10 {
      return errors.New("stopped after 10 redirects")
   }
   return nil
}
c.CheckRedirect
// CheckRedirect specifies the policy for handling redirects.
// If CheckRedirect is not nil, the client calls it before
// following an HTTP redirect. The arguments req and via are
// the upcoming request and the requests made already, oldest
// first. If CheckRedirect returns an error, the Client's Get
// method returns both the previous Response (with its Body
// closed) and CheckRedirect's error (wrapped in a url.Error)
// instead of issuing the Request req.
// As a special case, if CheckRedirect returns ErrUseLastResponse,
// then the most recent response is returned with its body
// unclosed, along with a nil error.
//
// If CheckRedirect is nil, the Client uses its default policy,
// which is to stop after 10 consecutive requests.
CheckRedirect func(req *Request, via []*Request) error
CheckRedirectErrUseLastResponseerrorc.checkRedirectErrUseLastResponseCheckRedirectfuncErrUseLastResponseerror

结果

http.ClientCheckRedirecthttp.ErrUseLastResponsefunc

例:

req, err := http.NewRequest("GET", url, nil)
if err != nil {
   return "", err
}

c := http.Client{
   CheckRedirect: func(req *http.Request, via []*http.Request) error {
      return http.ErrUseLastResponse
   },
   Timeout: 30 * time.Second,
}

resp, err := c.Do(req)