1. ホーム
  2. http

Go HTTP クライアントがリダイレクトを自動的に追跡しないようにするにはどうすればよいですか?

2023-09-13 08:01:30

質問

私は現在、REST API と対話するいくつかのソフトウェアを Go で書いています。私が問い合わせようとしている REST API のエンドポイントは、リソース URI を指す HTTP Location ヘッダーと一緒に HTTP 302 リダイレクトを返します。

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 's CheckRedirect 関数を使うと、基本的に HTTP リダイレクトをエラーのように扱わざるを得なくなります (エラーではありませんが)。

他のいくつかの場所で、HTTPクライアントの代わりにHTTPトランスポートを使用することを提案しているのを見ました -- しかし、私はこのREST APIと通信するためにHTTP Basic Authを使用する必要があるので、HTTPクライアントが必要なので、これをどのように動作させるかわかりません。

Basic Auth を使って HTTP リクエストを行う方法 -- リダイレクトに従わない -- で、エラーやエラー処理を投げない方法をどなたか教えていただけませんか?

どのように解決するのですか?

今はもっと簡単な解決方法があります。

client := &http.Client{
    CheckRedirect: func(req *http.Request, via []*http.Request) error {
        return http.ErrUseLastResponse
    },
}

このように http パッケージは自動的に次のことを知ります: "ああ、私はどんなリダイレクトも追うべきではない" しかし、どんなエラーも投げません。ソースコードのコメントより。

特殊なケースとして、CheckRedirect が ErrUseLastResponse.X を返した場合、最新のレスポンスが ErrUseLastResponse.X と共に返されます。 を返した場合、最新のレスポンスがそのボディとともに返されます。 を閉じたまま、nilエラーとともに返されます。