テック技報最新号へ →
コード

Go: http.Server には必ず ReadHeaderTimeout を設定する

http.ListenAndServe や素の &http.Server{} はタイムアウトがすべて0(=無制限)。ヘッダーを少しずつ送り続けるクライアント(Slowloris)に接続と goroutine を握られ続ける。

@amitsinha__07 · 2026-10-16
#go#net-http#security#timeout

書き方

go
srv := &http.Server{
    Addr:              ":8080",
    Handler:           mux,
    ReadHeaderTimeout: 5 * time.Second,  // ヘッダーを読み終えるまで
    ReadTimeout:       30 * time.Second, // ボディまで含めて読み終えるまで
    WriteTimeout:      30 * time.Second, // レスポンスを書き終えるまで
    IdleTimeout:       120 * time.Second, // keep-alive で次のリクエストを待つ時間
}
log.Fatal(srv.ListenAndServe())
  • ReadHeaderTimeout が0だと ReadTimeout が使われ、両方0ならヘッダー読み込みに期限がない。
  • IdleTimeout が0だと ReadTimeout が使われる。

どの値を付けるか

  • 最低限 ReadHeaderTimeout だけは付ける。 ハンドラーの処理時間に関係しないので、どんなサーバーでも副作用なく入れられる。
  • ReadTimeout / WriteTimeout は接続全体に効くので、大きなアップロード、SSE、長いストリーミングがあると途中で切れる。そういうハンドラーがあるなら、全体には付けずに http.NewResponseController(w).SetReadDeadline(...) / SetWriteDeadline(...)(Go 1.20+)でハンドラーごとに設定する。
  • ハンドラーの処理時間そのものを制限したいなら http.TimeoutHandler か context.WithTimeout。

見つけ方

gosec の G112 が ReadHeaderTimeout の付け忘れを指摘する(golangci-lint 経由でも使える)。

出典

X の元の投稿を開く