0
0

More than 1 year has passed since last update.

自分用GoでAPIを作る前に作るHttpClientラッパー

Last updated at Posted at 2022-01-04

Go で API を作るときは実際にサーバを起動して HTTP で叩くテストを作りたいので HTTP で叩くのを簡単にする自分用ツール。認証を回避できない環境で Swagger とか POSTMAN を手作業でAuth通して叩くのは面倒なので Go Test 上で認証して叩くことができる。おまけでレスポンスの Unmarshalもできる。GitHubはここ
いつでもAPIが叩けると精神衛生上良いし、フロントからエラー報告が来た時もすぐ検証ができる。
GitHub にアクセスできない仕事場が稀に良く有るので貼り付けさせてください。

使い方


// ここまで省略。 Server を起動しておいてから以下を実行するテストコードを書く。
// サーバー接続情報を作る
    k := Knocker{"127.0.0.1", 8080, ""}
// シンプルな Get ただし認証が通らない。b は res.Body の文字列
    t.Run("Required authorization token not found", func(t *testing.T) {
        res, b, err := k.Knock(http.MethodGet, "/private", nil, nil)
        if err != nil {
            panic(err)
        }
        assert.Equal(t, 401, res.StatusCode)
        assert.Equal(t, b, "Required authorization token not found\n")
    })
// 認証を通してから Get
    t.Run("Auth and OK", func(t *testing.T) {
        res, _, err := k.Auth(http.MethodGet, "/auth", nil)
        if err != nil {
            panic(err)
        }
// レスポンスの中身が検証しやすいように Unmarshal する機能が入っている。
        v := &PrivateResponse{}
        res, _, err = k.Knock(http.MethodGet, "/private", nil, v)
        if err != nil {
            panic(err)
        }
        assert.Equal(t, 200, res.StatusCode)
        assert.Equal(t, v.Tag, "Go")
    })
// 略

// Private api サーバ側でレスポンスを作っているコード
var private = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    reply:= PrivateResponse{
        Title: "jwt token が無いとアクセスできないはず",
        Tag:   "Go",
    }
    json.NewEncoder(w).Encode(reply)
})

// Private Response サーバ側のレスポンス構造体。テストからそのまま参照して使う。
type PrivateResponse struct {
    Title string
    Tag   string
}


実コード。


// Knocker is http client wrapper that Keep connection strings and Bearer token.
type Knocker struct {
    Host  string
    Port  int
    Token string
}

// Knock send request with Bearer token and unmarshal response json.
func (k *Knocker) Knock(method string, path string, param io.Reader, v interface{}) (response *http.Response, body string, err error) {
    url := fmt.Sprintf("http://%s:%d%s", k.Host, k.Port, path)
    request, err := http.NewRequest(method, url, param)
    if err != nil {
        return nil, "", err
    }
    if k.Token != "" {
        request.Header.Add("Authorization", "Bearer "+k.Token)
    }
    res, err := http.DefaultClient.Do(request)
    if err != nil {
        return nil, "", err
    }
    defer func() {
        err := res.Body.Close()
        if err != nil {
            panic(err)
        }
    }()
    resBody, err := ioutil.ReadAll(res.Body)
    if err != nil {
        return nil, "", err
    }

    if v != nil {
        if err := json.Unmarshal(resBody, v); err != nil {
            return nil, "", err
        }
    }

    return res, string(resBody), nil
}

// Auth send request and keep response string in Token.
func (k *Knocker) Auth(method string, path string, param io.Reader) (response *http.Response, body string, err error) {
    response, body, err = k.Knock(method, path, param, nil)
    k.Token = body
    return
}

あ。パラメータPOSTするテスト書き忘れた…明日で良いか。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0