我目前正在用 Go 编写一些与 REST API 交互的软件。我尝试查询的 REST API 端点返回 HTTP 302 重定向以及指向资源 URI 的 HTTP Location 标头。
我正在尝试使用我的 Go 脚本来获取 HTTP Location 标头以供以后处理。
这是我目前为实现此功能所做的工作:
package main import ( "errors" "fmt" "io/ioutil" "net/http" ) var BASE_URL = "https://api.example.com/v1" var STORMPATH_API_KEY_ID = "xxx" var STORMPATH_API_KEY_SECRET = "xxx" func noRedirect(req *http.Request, via []*http.Request) error { return errors.New("Don't redirect!") } func main() { client := &http.Client{ CheckRedirect: noRedirect } req, err := http.NewRequest("GET", BASE_URL+"/tenants/current", nil) req.SetBasicAuth(EXAMPLE_API_KEY_ID, EXAMPLE_API_KEY_SECRET) resp, err := client.Do(req) // If we get here, it means one of two things: either this http request // actually failed, or we got an http redirect response, and should process it. if err != nil { if resp.StatusCode == 302 { fmt.Println("got redirect") } else { panic("HTTP request failed.") } } defer resp.Body.Close() }
这对我来说有点像黑客。通过覆盖http.Client‘sCheckRedirect函数,我基本上被迫将 HTTP 重定向视为错误(它们不是)。
http.Client
CheckRedirect
我已经看到其他几个地方建议使用 HTTP 传输而不是 HTTP 客户端——但我不知道如何进行这项工作,因为我需要 HTTP 客户端,因为我需要使用 HTTP 基本身份验证与此 REST 进行通信应用程序接口。
你们中的任何人都可以告诉我一种使用基本身份验证发出 HTTP 请求的方法——同时不遵循重定向——不涉及抛出错误和错误处理?
现在有一个更简单的解决方案:
client := &http.Client{ CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse }, }
这样,http包自动知道:“啊,我不应该遵循任何重定向”,但不会抛出任何错误。从源代码中的注释:
http
作为一种特殊情况,如果 CheckRedirect 返回 ErrUseLastResponse,则返回最新的响应,其主体未关闭,并带有一个 nil 错误。