Edited at

Goで証明書を無視するクライアントでHTTP2を使いたい

More than 1 year has passed since last update.

ISUCONのベンチマーカーでGoのhttp.Clientをhttp2で使おうとしてハマった話 - Qiita

以前の記事では以下のように作ったクライアントを都度生成し、かつGoのコードにパッチを当てることで対応しました。

c := &http.Client{

Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}

Goにパッチを当てずに対応する方法はないでしょうか。Goにパッチを当てずに以下のようにするとどうでしょう。

c := &http.Client{

Transport: &http2.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}

これでも期待通りに動くように見えますが、これだとHTTP/1.1にしか対応してないサーバーに接続できなくなります。ちなみにHTTP/1.1までしか対応してないサーバーを立てたい場合は GODEBUG=http2server=0 ./server という感じに実行します。

ここで前回当てたパッチをもう一度確認します。

TLSClientConfigを上書きしつつ、http2も使えるようにするパッチ by catatsuy · Pull Request #80 · isucon/isucon6-final

を見てもらえれば分かりますが、TLSClientConfigを上書きすると飛ばされる処理で重要な処理は http2configureTransport です。これは golang.org/x/net/http2 をGoのコード内部に取り込むために使ったbundleコマンドによってリネームされた関数で、元々は configureTransport という関数名です。bundleコマンドについては下のリンクを参照してください。

Golangのbundleコマンド - Qiita

configureTransportはプライベートな関数ですが、内部でそれを呼び出すhttp2.ConfigureTransport関数があるので、それを呼び出せばよいです。なので以下のようにします。

tr := &http.Transport{

TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
if err := http2.ConfigureTransport(tr); err != nil {
log.Fatalf("Failed to configure h2 transport: %s", err)
}
c := &http.Client{
Transport: tr,
}

こうすればGoのコードにパッチを当てずに、今回期待する動きを実現できそうです。

ということでPR作りました。

パッチを当てずに証明書を無視するクライアントでHTTP2を使えるようにする by catatsuy · Pull Request #270 · isucon/isucon6-final