[51] [[HTTP/2]] は、 [DFN[[CODE(HTTP)@en[[[Upgrade:]] [[h2c]]]]]]
により [[HTTP]] over [[TCP]] から [[HTTP/2]] over [[TCP]]
へと移行する方法を規定しています。

* 代替

[52] この方法が広く実装されるかどうかは不明です。

[14] 通常は [[HTTPS]] ([[HTTP/2]] over [[TLS]]) を使うことが期待されています。
[[HTTPS]] では [CODE(HTTP)@en[Upgrade: h2c]] は使いません。

[15] そもそも [[TLS]] のない [[HTTP][素のHTTP]] は安全ではないので、使うべきではありません。
[[相互運用性]]のため、実装は [CODE(HTTP)@en[Upgrade: h2c]] 
に対応するべきでもありません。

* 仕様書

[REFS[
- [47] '''[CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-3.2>'''
- [9] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-5.1.1>
]REFS]

* 構文

[50] [[クライアント]]は、 [CODE(URI)@en[[[http:]]]] [[URL]]
にアクセスする場合、 [[HTTP/1.1]] [[要求]]の [CODE(HTTP)@en[[[Upgrade:]]]]
[[ヘッダー]]に、 [CODE(HTTP)@en[[[h2c]]]] と指定します [SRC[>>47]]。

[53] その場合、[CODE(HTTP)@en[[[HTTP2-Settings:]]]] [[ヘッダー]]をちょうど1つ指定しなければ[['''なりません''']] [SRC[>>47]]。

;; [54] 必然的に [CODE(HTTP)@en[[[Connection:]]]] [[ヘッダー]]に
[CODE(HTTP)@en[[[Upgrade]]]] と [CODE(HTTP)@en[[[HTTP2-Settings]]]]
を指定することになります。

;; [55] [[要求]]に [[payload body]] があれば、それも [[HTTP/2]] に切り替わる前に送る必要があります。
次の[[要求]]を送れるようになるまでの遅延を嫌う場合は、
[CODE(HTTP)@en[[[OPTIONS]]]] [[要求]]をかわりに送ることができます。 [SRC[>>47]]

;; [4] [CODE(HTTP)@en[[[Upgrade:]]]] の構文の項も参照。

* 文脈

[3] [[クライアント]]は [[TLS]] 上の [[HTTP]] で [CODE(HTTP)@en[[[Upgrade: h2c]]]]
を指定してはならないと思われます。

;; [5] [CODE(HTTP)@en[[[Upgrade:]]]] の文脈の項も参照。

* 処理

;; [6] [CODE(HTTP)@en[[[Upgrade:]]]] の処理の項も参照。

[FIG(sequence)[
:C:[[クライアント]]
:S:[[サーバー]]
:C -> S:[[HTTP/1.1]] [CODE(HTTP)@en[[[Upgrade: h2c]]]] [CODE(HTTP)@en[[[HTTP2-Settings:]] ...]] ※
:S -> C:[[HTTP/1.1]] [CODE(HTTP)[[[101]]]] [CODE(HTTP)@en[[[Upgrade: h2c]]]]
:C ## S:[[HTTP/2]] [[接続序文]]
:S -> C:[[HTTP/2]] ※への[[応答]]
]FIG]

[57] [[サーバー]]は、[[HTTP/2]] に対応していれば、 [CODE(HTTP)[[[101]]]]
[[応答]]を返します。その末尾の[[空行]]の直後から [[HTTP/2]] [[フレーム]]を送信できます。
[SRC[>>47]]

[56] [[サーバー]]は、 [[HTTP/2]] に対応していなければ、
[CODE(HTTP)@en[[[Upgrade:]]]] を無視して通常通り [[HTTP/1.1]] で[[応答]]を返すことになります。

[61] [[サーバー]]は、 [[TLS]] 上の [[HTTP]] なら [CODE(HTTP)@en[[[Upgrade:]] [[h2c]]]]
を無視しなければならないと考えられます。

[62] [[サーバー]]は、[[要求]]に [CODE(HTTP)@en[[[HTTP2-Settings:]]]] [[ヘッダー]]が複数あるか、
1つもなければ、[[HTTP/2]] に切り替えては[['''なりません''']] [SRC[>>47]]。

[63] [[サーバー]]は、[[HTTP/2]] に切り替える場合、
[CODE(HTTP)@en[[[HTTP2-Settings:]]]] [[ヘッダー]]の値を通常の 
[CODE[[[SETTINGS]]]] [[フレーム]]と同じように解釈します [SRC[>>47]]。

[18] [CODE(HTTP)@en[[[HTTP2-Settings:]]]] [[ヘッダー]]の
[[base64url]] [[復号]]や[[フレーム]]解釈によりエラーが検出された場合にどうするべきなのかは不明です。
切り替えずに [[HTTP/1.1]] で処理を続けるべきなのでしょうか。

[2] [CODE(HTTP)[[[101]]]] [[応答]]が暗示的な [[acknowledgement]] となるため、
明示的な [[acknowledgement]] の [CODE(HTTP)@en[[[SETTINGS]]]]
[[フレーム]]は不要です。 [SRC[>>47]]

[58] [[HTTP/2]] に切り替えた場合、[[サーバー]]が最初に送る[[フレーム]]は、
[CODE[[[SETTINGS]]]] [[フレーム]]の [[server connection preface]] 
でなければ[['''なりません''']] [SRC[>>47]]。

[59] [[クライアント]]は、[CODE(HTTP)[[[101]]]] [[応答]]を受信したら、
[CODE[[[SETTINGS]]]] [[フレーム]]を含む [[connection preface]]
を送信しなければ[['''なりません''']] [SRC[>>47]]。

[7] 切り替えた場合、[[サーバー]]は、次の[[ストリーム]]を作成します [SRC[>>47]]。
[FIG(list members)[
[FIGCAPTION[
[[ストリーム]]
]FIGCAPTION]
:[[ストリーム識別子]]:[CODE[[[1]]]]
:状態:[[half-closed (remote)]]
:[[ストリーム優先度]]:[[既定優先度]]
]FIG]

[8] 切り替えた場合、[[クライアント]]は、次の[[ストリーム]]を作成します。
[FIG(list members)[
[FIGCAPTION[
[[ストリーム]]
]FIGCAPTION]
:[[ストリーム識別子]]:[CODE[[[1]]]] [SRC[>>47, >>9]]
:状態:[[half-closed (local)]] [SRC[>>47, >>9]]
:[[ストリーム優先度]]:[[既定優先度]] [SRC[>>47]]
]FIG]

[60] 切り替えた場合、[[サーバー]]は切り替え前の [[HTTP/1.1]] 
[[要求]]に[[応答]]しなければ[['''なりません''']]。
[[ストリーム識別子]]は、 [CODE[[[1]]]] とします。 [SRC[>>47]]

* メモ

[10] [[TLS]] のない素の [[TCP]] 上の [[HTTP]] は、現在では危険と考えられています。
[[Webブラウザー]]開発者や[[Web標準]]の開発者の間では、 [[HTTPS]]
でない [[HTTP]] における新機能の導入を不適切とみなす流れが10年代中頃に固まってきています。

[11] [[IETF]] は本機能を [[HTTP/2]] 仕様の一部に含めていますが、
[[Webブラウザー]]が実装するのかどうか、[[Webブラウザー]]が対応しないとしたら
[[Webサーバー]]が実装するのかどうかには、疑問が持たれています。

;; [12] しかも [[HTTP/1.1]] の [CODE(HTTP)@en[[[Upgrade:]]]] は
[[WebSocket]] を除き成功例がなく、 [[TLS]] の問題がなかったとしても、
[[相互運用性]]と[[セキュリティー]]を十分確保して広く実装できたかは怪しいかもしれません。

[FIG(quote)[
[FIGCAPTION[
[13] [CITE@ja[HTTP/2 プロトコルネゴシエーション方法と ATS での実装 - Yahoo! JAPAN Tech Blog]]
([TIME[2016-03-02 18:02:58 +09:00]] 版)
<http://techblog.yahoo.co.jp/infrastructure/http2/ats_http2_pn/>
]FIGCAPTION]

> ATS には現状 HTTP アップグレードメカニズムを使用した HTTP/2 へのアップグレードには対応しておらず、NPN もしくは ALPN によるプロトコルネゴシエーションのみサポートされている状態です。しかしながらアップグレード対応の為の実装作業はそれほど大掛かりな作業ではなく、http スキームからのネゴシエーション方法もサポートしておきたいため(本稿のためのネタ作りも兼ねて!)今回実装してパッチを送りました。

]FIG]
