メインコンテンツへスキップ

Go Proposal Weekly Digest

Go言語のproposal更新を毎週お届け

#72039accepted

x/net/http2/h2c: deprecate h2c package

ステータス変更: likely_accept accepted

要約

AIによる要約であり、誤りを含む場合があります。

概要

golang.org/x/net/http2/h2c パッケージは、TLSなしで動作する暗号化されていないHTTP/2接続(h2c)をGoで扱うためのパッケージです。Go 1.24で標準ライブラリ net/http に同等機能が組み込まれたことを受け、このパッケージをdeprecate(非推奨化)するproposalが提出され、正式に承認されました。

ステータス変更

likely_acceptaccepted
2026年4月8日に「likely accept」と判定された後、1週間のレビュー期間中に追加の異論が寄せられなかったため、2026年4月16日に正式に「accepted」となりました。提案内容に対してコンセンサスが形成されており、実装フェーズに移行します。

技術的背景

現状の問題点

h2c パッケージはもともと、標準ライブラリが暗号化なしのHTTP/2をサポートしていなかった時期(2018年頃)に、gRPCなど内部サービス間通信の需要に応えるために x/net に追加されました(背景: #14141)。
しかし、このパッケージには以下の問題があります。

  • RFC 9113による非推奨: h2cパッケージが実装しているHTTPアップグレード機能(Upgrade: h2c ヘッダーによるHTTP/1.1からHTTP/2への切り替え)は、RFC 9113(Section 3.1)にて「広く普及しなかった」として非推奨とされています
  • 実装品質の問題: プロトコルアップグレード時に最初のリクエスト全体をメモリに読み込む必要があり、バグも多く含んでいました(CL 407454で修正)。サーバー側のみの対応でクライアント側のアップグレード実装がないため、アップグレード機能のテストカバレッジも存在しません
  • Go 1.24で代替手段が標準化: Go 1.24で net/httpServer.Protocols および Transport.Protocols が追加され、「prior knowledge(事前知識)」方式によるh2cが標準サポートされるようになりました

提案された解決策

golang.org/x/net/http2/h2c パッケージをdeprecate(非推奨)とし、標準ライブラリの net/http で提供されているネイティブなh2cサポートへの移行を促します。
Go 1.24以降、以下の方法で暗号化なしHTTP/2を利用できます。

  • サーバー側: Server.ProtocolsUnencryptedHTTP2 を設定
  • クライアント側: Transport.ProtocolsUnencryptedHTTP2 を含め HTTP1 を除外

これによって何ができるようになるか

h2c パッケージが非推奨化されることで、開発者は外部パッケージへの依存なしに標準ライブラリのみでh2cサポートを実装できます。内部サービス間通信(マイクロサービス、gRPC代替、ロードバランサーのSSL終端後のバックエンド通信など)においてクリーンなAPIを利用できるようになります。

コード例

// Before: h2cパッケージを使った従来の書き方
import (
    "golang.org/x/net/http2"
    "golang.org/x/net/http2/h2c"
)
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello world")
})
h2s := &http2.Server{}
server := &http.Server{
    Addr:    ":8080",
    Handler: h2c.NewHandler(handler, h2s), // h2cパッケージでラップが必要
}
log.Fatal(server.ListenAndServe())
// After: Go 1.24以降の標準ライブラリを使った書き方
import "net/http"
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello world")
})
var protocols http.Protocols
protocols.SetUnencryptedHTTP2(true)
protocols.SetHTTP1(true)
server := &http.Server{
    Addr:      ":8080",
    Handler:   handler,
    Protocols: &protocols, // 標準ライブラリで直接設定
}
log.Fatal(server.ListenAndServe())

議論のハイライト

  • RFC 9113による公式非推奨: h2cパッケージのコア機能であるHTTPアップグレード機構は、RFC 9113で既に非推奨とされており、パッケージ自体の存在意義が薄れています
  • 標準ライブラリへの機能統合: Go 1.24でネイティブなh2cサポート(prior knowledge方式)が net/http に追加されたこと(#67816)が、このdeprecation提案の直接的な背景です
  • プロトコルアップグレードは今後もサポート予定なし: 提案者(@neild)は、クライアント側のアップグレード実装が存在しないことやセキュリティリスク(h2c smuggling等)を踏まえ、今後も Upgrade: h2c をサポートする予定はないと明言しています
  • prior knowledge方式のみを標準化: RFC 9113が推奨する「事前知識」方式のみを標準ライブラリでサポートし、非推奨のアップグレード方式はサポート範囲外とするという設計判断がなされています
  • 非推奨化後の移行パス: パッケージをすぐに削除するのではなくdeprecate扱いとすることで、既存コードとの後方互換性を維持しながら段階的な移行を促します

関連リンク