当请求被重定向时,我可以检查响应吗?

huangapple go评论116阅读模式
英文:

Can I check response when the request is redirected?

问题

我们可以注册CheckRedirect来在请求重定向时检查下一个请求。有没有办法在第一个请求被重定向时获取响应?

英文:

We can register CheckRedirect to check the next request when the request is redirected. Is there a way that I can get the response for the first request when it's redirected?

答案1

得分: 2

目前的实现方式似乎无法默认查看响应(除非你自己实现Do()的功能)。
请参考src/net/http/client.go#L384-L399

如果应该重定向(shouldRedirect)响应,那么:

  • 如果响应体很小,读取响应体以便底层TCP连接可以被重用。
  • 如果读取失败,Transport也不会重用它,所以不需要检查错误。
  • 如果响应没有ContentLength或者ContentLength小于等于maxBodySlurpSize(2KB),则将响应体拷贝到ioutil.Discard中。
  • 关闭响应体。
  • 如果响应头中没有"Location"字段,将err设置为"%d response missing Location header"的格式化错误信息。
  • 更新base为req.URL。
  • 将req添加到via切片中。
  • 继续下一次循环。
英文:

The way it is currently implemented, it doesn't seem possible to have a look at the response by default (unless you implement yourself what Do() does).
See src/net/http/client.go#L384-L399:

  1. if shouldRedirect(resp.StatusCode) {
  2. // Read the body if small so underlying TCP connection will be re-used.
  3. // No need to check for errors: if it fails, Transport won't reuse it anyway.
  4. const maxBodySlurpSize = 2 << 10
  5. if resp.ContentLength == -1 || resp.ContentLength <= maxBodySlurpSize {
  6. io.CopyN(ioutil.Discard, resp.Body, maxBodySlurpSize)
  7. }
  8. resp.Body.Close()
  9. if urlStr = resp.Header.Get("Location"); urlStr == "" {
  10. err = fmt.Errorf("%d response missing Location header", resp.StatusCode)
  11. break
  12. }
  13. base = req.URL
  14. via = append(via, req)
  15. continue
  16. }

答案2

得分: 1

你想对第一个回复做什么?这将会相当无聊。

我认为最明智的做法是禁用自动跟随重定向(始终从CheckRedirect返回非nil错误),并自己处理重定向,在这种情况下,你可以完全访问所有的请求/响应。

英文:

What do you want to do with the first response? It will be pretty boring.

I think the most sensible thing would be to disable automatically following redirects (always return a non-nil error from CheckRedirect) and handle the redirection yourself in which case you have full access to all requests/responses.

答案3

得分: 0

我的解决方法是:

可以通过自定义的RoundTripper来修补任何HTTP请求/响应,包括重定向:

  1. type RedirectChecker struct{}
  2. func (RedirectChecker) RoundTrip(req *http.Request) (*http.Response, error) {
  3. // 例如,在发送请求之前修补请求
  4. req.Header.Set("user-agent", "curl/7.64.1")
  5. resp, err := http.DefaultTransport.RoundTrip(req)
  6. if err == nil && resp != nil {
  7. switch resp.StatusCode {
  8. case
  9. http.StatusMovedPermanently,
  10. http.StatusFound,
  11. http.StatusTemporaryRedirect,
  12. http.StatusPermanentRedirect:
  13. // 例如,停止进一步的重定向
  14. // 大致相当于http.ErrUseLastResponse
  15. resp.StatusCode = http.StatusOK
  16. // 例如,读取Set-Cookie头
  17. // 不幸的是,cookie jar不能正确处理重定向
  18. // 这就是我来到这个问题的原因...
  19. fmt.Printf("%+v", resp.Cookies())
  20. }
  21. }
  22. }
  1. httpClient := &http.Client{Transport: RedirectChecker{}}
  2. httpClient.Do(...)
英文:

My workaround for this:

Any http request / response could be patched within a custom RoundTripper, including redirects:

  1. type RedirectChecker struct{}
  2. func (RedirectChecker) RoundTrip(req *http.Request) (*http.Response, error) {
  3. // e.g. patch the request before send it
  4. req.Header.Set("user-agent", "curl/7.64.1")
  5. resp, err := http.DefaultTransport.RoundTrip(req)
  6. if err == nil && resp != nil {
  7. switch resp.StatusCode {
  8. case
  9. http.StatusMovedPermanently,
  10. http.StatusFound,
  11. http.StatusTemporaryRedirect,
  12. http.StatusPermanentRedirect:
  13. // e.g. stop further redirections
  14. // roughly equivalent to http.ErrUseLastResponse
  15. resp.StatusCode = http.StatusOK
  16. // e.g. read the Set-Cookie headers
  17. // unfortunately cookie jars do not handle redirects in a proper manner
  18. // and that's why I came to this question...
  19. fmt.Printf("%+v", resp.Cookies())
  20. }
  21. }
  22. }
  1. httpClient := &http.Client{Transport: RedirectChecker{}}
  2. httpClient.Do(...)

huangapple
  • 本文由 发表于 2015年4月25日 21:17:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/29865691.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定