Go の http.Client が送り直す要求と返すエラー

結論 http.Client は 301 / 302 / 303 の転送に従うと、DELETE・PUT・POST を本文なしの GET にして転送先へ送る。DELETE への 302 が一覧へ転送されると、一覧の GET が 200 を返し、何も消さずに成功として返る。307 / 308 はメソッドと本文を保つ 再利用した接続が応答の前に切られると、HTTP/1.1 の Transport は GET などと Idempotency-Key 付きの要求だけを、新しい接続で送り直す。HTTP/2 では GET でも送り直さず、connection reset by peer を返す 本文を送り直せるのは GetBody があるときだけで、http.NewRequest が GetBody を付けるのは *bytes.Buffer / *bytes.Reader / *strings.Reader だけ。それ以外の io.Reader では、307 は転送されずにそのまま返り、読み切った要求をもう一度 Do すると空の本文がエラーなしに届く HTTP/2 の接続は MaxIdleConnsPerHost の数を超えても閉じられない。取り置き 2 本の設定で、張った 8 本を残して使い回した。MaxConnsPerHost は同時に張りに行く接続を絞るが、HTTP/2 の接続の数の上限にはならない (サーバの同時ストリームが 2 のとき、1 にしても 4-6 本張った) 失敗は *url.Error で返り、Error() にクエリ込みの URL が入る。%w で包んでも、文字列にすれば URL が出る。接続リセットも接続拒否も net.Error を満たすので、タイムアウトかどうかは Timeout() で分ける 以下は go1.26.4 / linux/amd64 で実測した。サーバは net/http/httptest で手元に立て、HTTP/2 は EnableHTTP2 と StartTLS で話させた。各節のコードは main.go 1 つで、go run で動く。 ...

2026-10-26 ·  2026-10-26 · 10 分 · 1942 文字