canonicalheader は net/http.Header で非正規形式のヘッダーキーが使用されていないかをチェックするツールです。
解決する問題 Go の http.Header はキーを正規形式(Canonical Form)で管理します。正規形式とは、ハイフンで区切られた各単語の先頭を大文字にする形式(例: Content-Type)です。非正規形式のキーを直接使うと、Set や Get が正規化するため動作はしますが、コードの一貫性が損なわれ、map として直接アクセスする際にバグを引き起こす可能性があります。
1 2 3 4 5 6 func SetHeaders (h http.Header) { h.Set("content-type" , "application/json" ) h.Set("X-REQUEST-ID" , "abc123" ) h.Set("accept-encoding" , "gzip" ) }
1 2 3 4 5 6 func SetHeaders (h http.Header) { h.Set("Content-Type" , "application/json" ) h.Set("X-Request-Id" , "abc123" ) h.Set("Accept-Encoding" , "gzip" ) }
設定 公式ドキュメント
設定オプションはありません。有効化するだけで動作します。
1 2 3 4 5 6 version: "2" linters: enable: - canonicalheader
オプション golangci-lint 経由では設定オプションはありません。
サンプル 検出例 1 2 3 4 5 6 7 8 9 10 11 func example (w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type" , "text/html" ) w.Header().Add("x-custom-header" , "value" ) _ = r.Header.Get("accept-language" ) r.Header["content-type" ] = []string {"text/plain" } }
修正例 1 2 3 4 5 6 7 func example (w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type" , "text/html" ) w.Header().Add("X-Custom-Header" , "value" ) _ = r.Header.Get("Accept-Language" ) r.Header.Set("Content-Type" , "text/plain" ) }
注意点
http.Header.Set() や Get() は内部で http.CanonicalHeaderKey() を呼んで正規化するため動作上の問題は起きにくいが、コードの可読性と一貫性のために正規形式で記述すべき
http.Header を map[string][]string として直接操作する場合は正規化されないため、非正規形式のキーが残りバグの原因になる
正規形式の変換ルール: ハイフン区切りの各単語の先頭を大文字、残りを小文字にする(例: accept-encoding → Accept-Encoding)
参考リンク