[313] [DFN[[CODE(HTTP)@en[[[Upgrade:]]]]]] [[ヘッダー]]は、
同じ[[接続]]を使って [[HTTP/1.1]] から他の[[プロトコル]]へと移行するための仕組みです
[SRC[>>311]]。事実上 [[WebSocket]] 専用であり、 [[WebSocket接続の確立]]で使います。

* 仕様書

[REFS[
- [311] '''[CITE@en[RFC 7230 - Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing]] ([TIME[2014-06-07 01:59:35 +09:00]] 版) <https://tools.ietf.org/html/rfc7230#section-6.7>'''
- [10] [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>
- [18] [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-8.1.2.2>
]REFS]

* 意味

[20] [CODE(HTTP)@en[[[Upgrade:]]]] は、[[HTTP/1.1]] から [[WebSocket]]
に切り替えるために使います。

;; [24] [[HTTP]] の改訂版を含め、色々な他のプロトコルへの切り替えを想定していたようですが、
実際に使われているのは [[WebSocket]] だけです。

;; [25] [[HTTP]] の改訂版などより高機能なプロトコルへの切り替えを想定して
「[CODE(HTTP)@en[Upgrade]]」という名前にしたのでしょうが、 [[WebSocket]]
が [[HTTP]] の「upgrade」版というわけでもありません。

[438] [CODE(HTTP)@en[[[Upgrade:]]]] は、下位層プロトコルの切り替えには使えません [SRC[>>311]]。
また、現在の[[接続]]を再利用しない切り替えにも使えません [SRC[>>311]]。

* 構文

[319] [[欄値]]は、1つ以上の[[プロトコル]]の[[リスト]] ([CODE[#]]) です [SRC[>>311]]。

[FIG(railroad)[
- [[プロトコル]]
- *
-- [[OWS]]
-- [CODE[[[,]]]]
-- [[OWS]]
-- [[プロトコル]]
]FIG]

[320] [[プロトコル]]は、名前、または名前と [CODE[[[/]]]] と版を並べたものです
[SRC[>>311]]。

;; [321] [[プロトコル]]の詳細と値の一覧は、 [[[CODE(ABNF)@en[protocol]] (HTTP)]] 
の項を参照してください。

* 文脈

[314] [[クライアント]]は、[CODE(HTTP)@en[[[Upgrade:]]]] [[ヘッダー]]を[[要求]]に含めることができます
[SRC[>>311]]。

;; [436] [[クライアント]]が [CODE(HTTP)@en[[[Upgrade:]]]] を送信しても、
[[鯖]]が切り替えを示すまでは、 [[HTTP/1.1]] のままです。 [CODE(HTTP)@en[[[Upgrade:]]]]
が含まれる[[メッセージ]]は最後まで [[HTTP/1.1]] でなければなりません。

[316] [CODE(HTTP)@en[[[Upgrade:]]]] [[ヘッダー]]は、[[クライアント]]が[[鯖]]に対して、
最後の[[要求]]を送る前に指定したいずれかの[[プロトコル]]に切り替えることを要請するものです [SRC[>>311]]。
[[プロトコル]]の順序は、優先順を表しています [SRC[>>311]]。

[315] [CODE(HTTP)@en[[[Upgrade:]]]] [[ヘッダー]]は複数指定できます。

[435] この[[ヘッダー]]は [[HTTP/1.1]] で定義されています。 [[HTTP/1.0]] や
[[HTTP/0.9]] では使えません。

[14] [[HTTP/2]] では [CODE(HTTP)@en[[[Upgrade:]]]] を[[生成]]しては[['''なりません''']]
[SRC[>>18]]。
[[状態符号]] [CODE(HTTP)[[[101]]]] も使えないことになっています。

[322] [[鯖]]は、 [CODE(HTTP)[[[101]]]] [[応答]]に新しい[[プロトコル]]を表す
[CODE(HTTP)@en[[[Upgrade:]]]] [[ヘッダー]]を含めなければ[['''なりません''']] [SRC[>>311]]。
複数の階層の[[プロトコル]]を切り替える場合には、[[昇順]]にしなければ[['''なりません''']]
[SRC[>>311]]。

;; [324] [[昇順]]ってどちらでしょうか??

[327] [[鯖]]は、 [CODE(HTTP)[[[426]]]] [[応答]]において
移行可能な[[プロトコル]]を示す [CODE(HTTP)[[[Upgrade:]]]]
[[ヘッダー]]を送らなければ[['''なりません''']] [SRC[>>311]]。
[[プロトコル]]の順序は、優先順を表します [SRC[>>311]]。

[428] [[鯖]]は、その他の[[応答]]にも、移行可能な[[プロトコル]]を表す
[CODE(HTTP)@en[[[Upgrade:]]]] [[ヘッダー]]を含めて構いません [SRC[>>311]]。
[[プロトコル]]の順序は、優先順を表します [SRC[>>311]]。

[21] [CODE(HTTP)@en[[[Upgrade:]]]] を指定する[[要求]]の
[[HTTP接続]]における位置は特に規定されていません。
[[接続]]を開いて最初の[[要求]]でも構いませんし、
途中でも構わないようです。

* 処理

[441] [[鯖]]は、 [CODE(HTTP)@en[[[Upgrade:]]]] [[要求]]に対し、
新しい[[プロトコル]]を選んで、 [CODE(HTTP)[[[101]]]] [[応答]]を返します。ただし、
[FIG(list)[
- [318] [[鯖]]は、現在の[[プロトコル]]を使い続けたい場合、無視して構いません [SRC[>>311]]。
- [434] [[鯖]]は、 [[HTTP/1.0]] [[要求]]の [CODE(HTTP)@en[[[Upgrade:]]]]
[[ヘッダー]]を無視しなければ[['''なりません''']] [SRC[>>311]]。
- [15] [[サーバー]]は、 [[HTTP/2]] で [CODE(HTTP)[[[101]]]] [[応答]]を返せません [SRC[>>10]]。
- [325] [[鯖]]は、[[クライアント]]が指定していない[[プロトコル]]に切り替えては[['''なりません''']]
[SRC[>>311]]。
- [326] [[鯖]]は、[[クライアント]]の指定した優先順は無視しても構いません [SRC[>>311]]。
]FIG]

;; [427] [CODE(HTTP)[[[101]]]] [[応答]]は新しい[[プロトコル]]ではなく、
まだ [[HTTP/1.1]] のままです。

[FIG(sequence)[
:C:[[クライアント]]
:S:[[鯖]]
:C -> S:[[要求]]
[PRE(HTTP code)[
[[Upgrade:]] [VAR[P]]
[[Connection:]] [[upgrade]]
]PRE]
:S -> C:[CODE(HTTP)[[[101]]]] [[応答]]
[PRE(HTTP code)[
[[Upgrade:]] [VAR[P]]
[[Connection:]] [[upgrade]]
]PRE]
:C ## S:[VAR[P]] に移行
]FIG]

[437] [[鯖]]は、 [CODE(HTTP)@en[[[Upgrade:]]]] [[ヘッダー]]の他に
[CODE(HTTP)@en[[[Expect:]]]] [[ヘッダー]]の値 [CODE(HTTP)[[[100-continue]]]]
が指定されていた場合には、 [CODE(HTTP)[[[101]]]] の前に [CODE(HTTP)[[[100]]]]
を送らなければ[['''なりません''']] [SRC[>>311]]。

[432] [[鯖]]は、 [CODE(HTTP)@en[[[Upgrade:]]]] を送信するときは、
[CODE(HTTP)@en[[[Connection:]]]] [[ヘッダー]]にも[[接続オプション]]
[CODE(HTTP)@en[[[upgrade]]]] を送信しなければ[['''なりません''']] [SRC[>>311]]。

;; [433] これによって、[[中間器]]が指定された[[プロトコル]]に対応していない時に切り替えを防ぐことができます。

;; [1] 防ぐことはできますが、[[キャッシュ]]の処理と [CODE(HTTP)@en[[[Upgrade:]]]]
は矛盾するので、[[キャッシュ可能メソッド]]で [CODE(HTTP)@en[[[Upgrade:]]]]
を使うのは得策ではなさそうです。

[17] [[HTTP/1.0]]/[[HTTP/1.1]] から [[HTTP/2]] に変換する[[中間器]]は、
[CODE(HTTP)@en[[[Connection:]]]] に [CODE(HTTP)@en[[[Upgrade]]]]
が明示されているか否かに関わらず、 [CODE(HTTP)@en[[[Upgrade:]]]]
[[ヘッダー]]があれば削除する[['''べきです''']] [SRC[>>18]]。

[19] [[HTTP/2]] では、 [CODE(HTTP)@en[[[Upgrade:]]]] が含まれる[[メッセージ]]は[[奇形]]です
[SRC[>>18]]。

* プロトコルの切り替え

[429] [[プロトコル]]の切り替え後の能力や性質は、新しい[[プロトコル]]に完全に依存します
[SRC[>>311]]。しかし、[[鯖]]は [CODE(HTTP)[[[101]]]] [[応答]]を送信した直後には、
元の[[要求]]に対する処理に相当するものを実行することが期待されています [SRC[>>311]]。
[[鯖]]は、新しい[[プロトコル]]が[[要求]]の意味を尊重できる場合を除き、
切り替えては[['''なりません''']] [SRC[>>311]]。 [CODE(HTTP)@en[[[OPTIONS]]]]
[[要求]]は、どんな[[プロトコル]]でも尊重される [SRC[>>311]] とされています。

[EG[
[430] 例えば [CODE(HTTP)@en[[[GET]]]] [[要求]]に [CODE(HTTP)@en[[[Upgrade:]]]]
が指定されていて、[[鯖]]が [CODE(HTTP)[[[101]]]] を返した場合、
[[鯖]]は新しいプロトコルに切り替えて [CODE(HTTP)[[[GET]]]] されていた[[資源]]を送るべきです。
]EG]

;; [431] 従って、特に実行したい [[HTTP]] 操作がなく、プロトコルの切り替えだけを行いたいときは、
[CODE(HTTP)@en[[[OPTIONS]]]] [[要求]]を使えば良いことになります。

;; [26] [[WebSocket]] は [CODE(HTTP)@en[[[GET]]]] [[要求]]を使っていますが、
必ずしも [CODE(HTTP)@en[[[GET]]]] [[要求]]に対する[[応答]]に相当するものであるとは言えませんし、
この [[HTTP]] の本来の想定に沿っているようには見えません。

[4] [[クライアント]]が対応していない [CODE(HTTP)[[[101]]]]
[[応答]]を受信した場合の[[クライアント]]の処理は、[CODE(HTTP)[[[101]]]]
を参照してください。

[22] 切り替えが完了する前に[[クライアント]]が [CODE(HTTP)@en[[[Upgrade:]]]]
を含む[[要求]]の次のデータを送信することは、明確には禁止されていません。
一方で[[サーバー]]がそれをどう処理するべきかも明確な規定はありません。
[[サーバー]]が [CODE(HTTP)@en[[[101]]]] [[応答]]を返す前に[[クライアント]]によって送信されていたデータがどこまでであるかを[[サーバー]]が判定する方法はありませんから、
[[サーバー]]は[[要求]]の後の部分はすべて切り替え後のデータと解釈するしかありません。

;; [23] [[サーバー]]が切り替えを拒否した場合は、そのデータは [[HTTP]]
として解釈されることになります。

* 具体的な切り替え手順

[5] 現在広く用いられているのは、 [[WebSocket]] です。その手順は
[[WebSocket接続の確立]]を参照してください。

[HISTORY[
[9] [[HTTP/2]] は [CODE(HTTP)@en[[[Upgrade:]] [[h2c]]]] による [[HTTP/2]] over [[TCP]]
への切り替えを規定しています。しかしすべての実装が対応しているわけではありません。

;; [[HTTP接続]]を参照。

[6] 過去に [[IETF]] は [CODE(HTTP)@en[[[Upgrade: TLS]]]] により [[HTTP]] over [[TLS]]
を実現することを試みましたが、失敗しました。

;; [CODE(HTTP)@en[[[Upgrade: TLS]]]] の歴史の項を参照。
]HISTORY]

[11] [[サーバー]]は、 [CODE[[[h2]]]] が指定されても無視しなければ[['''なりません''']]
[SRC[>>10]]。

;; [12] [[HTTP/2]] over [[TLS]] では [[ALPN]] が使われ、 [CODE(HTTP)@en[[[Upgrade:]]]]
は使えません。

;; [13] この規定より [CODE(HTTP)[[[h2]]]] という値は使えないはずですが、
[[IANA登録簿]]には予約としても登録されていないようです。[TIME[2015-05-18T12:23:38.300Z]]

[7] その他いくつかの[[プロトコル (HTTP)]]の値が限られた範囲で使われているようです。

[8] [[サーバー]]も[[クライアント]]も切り替え後のプロトコルの動作を把握しておく必要がありますから、
一般性を持たせた実装は困難かもしれません。今後次々と新しいプロトコルが登場する見込みもありませんから
([[HTTP/2]] 同様、[[ALPN]] を使うことになるでしょう。)、
そのような実装の必要も無さそうです。

* 歴史

[REFS[
- [312] [[RFC 2068]]
- [309] [[RFC 2616]]
]REFS]

[FIG(quote)[
[FIGCAPTION[
[308] RFC 2068 (HTTP/1.1) 14.41; RFC 2616 (HTTP/1.1) 14.42 Upgrade
]FIGCAPTION]

> The Upgrade general-header allows the client to specify what
additional communication protocols it supports and would like to use
if the server finds it appropriate to switch protocols. The server
MUST use the Upgrade header field within a 101 (Switching Protocols)
response to indicate which protocol(s) are being switched.

[CODE(HTTP)[Upgrade]] [[一般頭欄]]は、
[[クライアント]]が、どの追加の通信プロトコルに対応しており、
[[鯖]]がプロトコル切替えが適切であると判断した場合には使用したいと考えているのかを指定することができます。
鯖は、 [CODE(HTTP)[[[101]]]] (プロトコル切替) 応答中でどのプロトコルに切り替えるのかを示すために
[CODE(HTTP)[Upgrade]] 頭欄を使わなければ'''なりません'''。

>
- Upgrade        = "Upgrade" ":" 1#product

> For example,
- Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11

> The Upgrade header field is intended to provide a simple mechanism
for transition from HTTP/1.1 to some other, incompatible protocol. It
does so by allowing the client to advertise its desire to use another
protocol, such as a later version of HTTP with a higher major version
number, even though the current request has been made using HTTP/1.1.
This eases the difficult transition between incompatible protocols by
allowing the client to initiate a request in the more commonly
supported protocol while indicating to the server that it would like
to use a "better" protocol if available (where "better" is determined
by the server, possibly according to the nature of the method and/or
resource being requested).

[CODE(HTTP)[Upgrade]] 頭欄は、 HTTP/1.1 から何か他の、非互換なプロトコルに移行するための単純な機構を提供することを想定しています。クライアントは、
現在の要求は HTTP/1.1 を使って行いながらも、例えばより大きな大版番号を持つより新しい版の
HTTP のような、別のプロトコルを使いたいと思っているということを宣伝できます。
これによって、非互換プロトコル間の難しい移行が、
クライアントはより広く対応されているプロトコルで要求を初期化しつつ鯖に「よりよい」
プロトコルを利用可能なら使いたいことを示すことができるので、
容易になります。
(ここで「よりよい」とは、鯖によって、おそらく要求された[[方式]][[及び/又は]][[資源]]の性質に従って決定されます。)

> The Upgrade header field only applies to switching application-layer
protocols upon the existing transport-layer connection. Upgrade
cannot be used to insist on a protocol change; its acceptance and use
by the server is optional. The capabilities and nature of the
application-layer communication after the protocol change is entirely
dependent upon the new protocol chosen, although the first action
after changing the protocol MUST be a response to the initial HTTP
request containing the Upgrade header field.

[CODE(HTTP)[Upgrade]] 頭欄は、既存の[[転送層]][[接続]]上の[[応用層]]プロトコルの切替にのみ適用します。
[CODE(HTTP)[Upgrade]] をプロトコル変更を主張するのに使うことはできません。
鯖がそれを受け入れて使用するかどうかは任意選択です。
プロトコル変更後の応用層通信の能力と性質は選ばれた新しいプロトコルに完全に依存します。
但し、プロトコル変更後の最初の動作は [CODE(HTTP)[Upgrade]] 頭欄を含んだ初期
HTTP 要求への応答でなければ'''なりません'''。

> The Upgrade header field only applies to the immediate connection.
Therefore, the upgrade keyword MUST be supplied within a Connection
header field (section 14.10) whenever Upgrade is present in an
HTTP/1.1 message.

[CODE(HTTP)[Upgrade]] 頭欄は、直接接続にのみ適用します。
従って、 [CODE(HTTP)[Upgrade]] が HTTP/1.1 メッセージ中に存在するときには、
必ず [CODE(HTTP)[upgrade]] 見出し語を [CODE(HTTP)[[[Connection]]]] 頭欄中に供給しなければ'''なりません'''。

> The Upgrade header field cannot be used to indicate a switch to a
protocol on a different connection. For that purpose, it is more
appropriate to use a 301, 302, 303, or 305 redirection response.

[CODE(HTTP)[Upgrade]] 頭欄は、異なる接続上のプロトコルへの切替えを示すために使うことはできません。
その目的には、 [CODE(HTTP)[[[301]]]], [CODE(HTTP)[[[302]]]],
[CODE(HTTP)[[[303]]]] または [CODE(HTTP)[[[305]]]] の再指向応答を使うのがより適切です。

> This specification only defines the protocol name "HTTP" for use by
the family of Hypertext Transfer Protocols, as defined by the HTTP
version rules of section 3.1 and future updates to this
specification. Any token can be used as a protocol name; however, it
will only be useful if both the client and server associate the name with the same protocol.

この仕様書は、プロトコル名 [CODE(HTTP)[HTTP]] だけを、
ハイパー文転送プロトコルで使用するために、
3.1節の版規則とこの仕様書の将来の更新で定義される通り定義します。
任意の字句をプロトコル名として使うことができます。
しかし、それはクライアントと鯖がある名前を同じプロトコルと関連付けている場合に限って有用です。
]FIG]

[3] [[RFC 2817]] は [[HTTP]] から [[HTTP]] over [[TLS]] への切り替えに
[CODE(HTTP)@en[[[Upgrade:]] [[TLS/1.0]]]] を使うことを提案していました [SRC[>>307]]
(が普及しませんでした)。

[REFS[
- [307] [CITE@en[RFC 2817 - Upgrading to TLS Within HTTP/1.1]] ([TIME[2012-01-09 20:05:09 +09:00]] 版) <http://tools.ietf.org/html/rfc2817>
]REFS]

[443] [CITE@en[RFC 3507 - Internet Content Adaptation Protocol (ICAP)]]
( ([TIME[2014-06-08 07:17:07 +09:00]] 版))
<http://tools.ietf.org/html/rfc3507#page-13>

* 関連

[442] [[RTSP]] と [[SIP]] には、 [CODE(HTTP)@en[[[Upgrade:]]]] はありません。

[2] [[プロトコル]]の切り替えを伴わない[[クライアント]]からの要望を伝えるものとして、
[CODE(HTTP)@en[[[Expect:]]]]、[CODE(HTTP)@en[[[Prefer:]]]]、
[CODE(HTTP)@en[[[Accept:]]]] などにたような[[ヘッダー]]が他にもあります。

[16] [CODE(HTTP)@en[[[CONNECT]]]] [[要求メソッド]]は、実質的に [[HTTP]]
を終了させて[[トンネル]]に移行するものですが、 [CODE(HTTP)@en[[[Upgrade:]]]]
は使っていません。

[FIG(quote)[
[FIGCAPTION[
[27] [CITE[GDAX | API Reference]]
([TIME[2016-08-11 04:02:30 +09:00]])
<https://docs.gdax.com/#sandbox-urls>
]FIGCAPTION]

> FIX API
> https://fix-public.sandbox.gdax.com
> NOTE ON FIX API
> request.end();
> When connecting to the FIX API in Sandbox, you must start with an HTTP Upgrade request and set the Upgrade header to fix. After receiving a 101 Switching Protocols response from the server, you may continue using the connection as a regular FIX connection. Remember to use HTTPS for this.

]FIG]


[FIG(quote)[
[FIGCAPTION[
[28] [CITE@en[58745 – H2Upgrade do not works]]
( ([TIME[2017-03-27 21:41:35 +09:00]]))
<https://bz.apache.org/bugzilla/show_bug.cgi?id=58745>
]FIGCAPTION]

> 
> Upgrade: h2,h2c
> Connection: Upgrade

]FIG]


[FIG(quote)[
[FIGCAPTION[
[29] [CITE@en[Handling server replies with "Upgrade" header (HTTP/2 switch) · Issue #81 · jech/polipo]]
( ([TIME[2017-03-27 21:41:53 +09:00]]))
<https://github.com/jech/polipo/issues/81>
]FIGCAPTION]

> Server: Apache/2.4.18 (Unix)
> X-Powered-By: PHP/5.6.15
> Vary: Accept-Encoding,Cookie
> Cache-Control: max-age=3, must-revalidate
> WP-Super-Cache: Served supercache file from PHP
> Upgrade: h2,h2c

]FIG]


[30] [[Apache]] は [CODE[Upgrade: h2c]] に対応しているから、それは良いとして、
[CODE[[[Upgrade:]] [[h2]]]] は何だろう。。。


[31] [CITE@en[HTTP/2 | 2020 | The Web Almanac by HTTP Archive]]
([TIME[2021-04-24T09:26:21.000Z]])
<https://almanac.httparchive.org/en/2020/http2#upgrade>