emahiro/b.log

Drastically Repeat Yourself !!!!

Go で Response Header を差し込む

Overview

大した話じゃないですが久しぶりに http を色々ゴニョゴニョするコードを書いていたら忘れていたので備忘録

Response Header を差し込む

※ サンプルは httptest の Server を立ち上げています。

// application/json を Response Header の Content-Type に差し込む
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
                w.Header().Set("Content-Type", "application/json")
                w.WriteHeader(http.StatusOK)
                _, _ = w.Write([]byte(jsonString))
}))

ただし、WriteHeader関数最後に呼ばないと Response Header の情報が上書きされてしまいます。

以下のサンプルでは application/json が指定されず、 plain/text が Response Header の Content-Type に指定されてしまいます。

ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
                w.WriteHeader(http.StatusOK)
                w.Header().Set("Content-Type", "application/json")
                _, _ = w.Write([]byte(jsonString))
}))

これは WriteHeader の副作用によるもので公式のドキュメントにも記載されています。

// Changing the header map after a call to WriteHeader (or
// Write) has no effect unless the HTTP status code was of the
// 1xx class or the modified headers are trailers.

ref: https://pkg.go.dev/net/http#ResponseWriter

このため、Content-Type を指定して mock server 等を立ち上げたいときには、この振る舞いに注意することが必要になります。

余談

ResponseHeader を取り出す

これも大した話じゃないですが忘れてたので。以下のサンプルは Response Header の Content-Type を取り出します。

resp.Header.Get("Content-Type")

ちなみに以下でも取り出せますが、返り値が配列で返ってきます。
※ Go の http.Response の場合、Content-Type にはデフォルトで []string{"application/json;", "charset=utf-8"} 等 string の slice の状態で Header の map が格納されてるため。