保安

ws: URL, wss: URL

[25] ws:WebSocket over TCPwss:WebSocket over TLS over TCP によってアクセスできる WebSocket 資源を表す URL scheme です。

仕様書

構文

[3] URL scheme://authoritypath、 省略可能な query で構成されます。 query がある場合は、 直前に ? が必要です。 >>2

  1. URL scheme
  2. ://
  3. authority
  4. path
  5. ?
    1. ?
    2. query

[12] 素片識別子を使ってはなりません >>2

URL scheme

[4] URL scheme は、 ws または wss です >>2

[10] wss であれば、当該 URL「保安」 ("secure") であり、 the secure flag is set といいます >>2

authority

[5] authority は、ホストと、省略可能な port です。 port がある場合は直前に : が必要です。 >>2

  1. ホスト
  2. ?
    1. :
    2. port

[6] ホストport は、 RFC 3986 の定義が参照されています >>2。 現実には URL Standard に従い解釈されるものと思われます。

[9] ws:既定のポート80wss:既定のポート443 です >>2

資源名

[7] path は、 RFC 3986 path-abempty です >>2

[8] query は、 RFC 3986 query が参照されています >>2

[11] 資源名 (resource name) は、

  1. path が空なら、 /
  2. path
  3. query が非空なら、 ?
  4. query

... を連結したものです >>2

[21] 資源名の解釈は、 HTTP の場合と同じく、サーバーに委ねられています。 クライアントはその意味を一般的に解釈することはできません。

[22] 例えば queryapplication/x-www-form-urlencoded 形式にすることができますが、そう解釈して良いのはサーバーと、 サーバーがそのように解釈していることを知っているスクリプトだけです。 サーバーがどう解釈するか事前に知識を得ていないクライアントがそのように解釈してはいけません。

[23] WebSocketコンストラクターUTF-8 としてURLの解決を行うと規定されています。 つまりスクリプト非ASCII文字query に含めると、 UTF-8 としてパーセント符号化されてサーバーに送信されます。 パス部分の非ASCII文字も、 UTF-8 としてパーセント符号化されます。 ですから、WebSocketクライアントパーセント符号化UTF-8 として解釈することが好ましいと思われます。

[24] 元々パーセント符号化されているものは再変換されませんから、 UTF-8 以外の文字コードバイナリーデータを含めることも理論上は可能です。 しかし実用上は常に UTF-8 を使うとするべきでしょう。

妥当性

[29] RFCWebSocket接続の確立URL の妥当性を確認することを求めていましたが、 その検査方法の詳細は不明でした。その曖昧な規定は Fetch StandardHTML Standard の規定の厳密化により死文化しました。

[13] WebSocket接続の確立は、 ws:/wss: URL が妥当なものであるかどうか確認し、非妥当なら失敗します。

[14] どのような検査か完全に明記はされていませんが、素片識別子が含まれる場合や、 ポートが数値でない文字列の場合、// が含まれない場合などが該当しそうです。

[15] WebSocketRFCRFC 3986 を参照しているので非ASCII文字は使えないことになりますが、 実際には URL Standard に従い構文解析正準化が行われた後の URL が使われますから、非ASCII文字正準化の段階で ASCII文字に変換されています。

構文解析

[28] かつては独自の構文解析の手続きが HTML Standard で規定されていましたが、 その後 URL Standard が整備されたことから、削除されました。 ws:wss:URL も通常の URLの構文解析が行われた後、 new WebSocket の処理で最低限の検査を行い、プロトコルで利用されることになります。

[19] WebSocket URLの部品の構文解析 (parse a WebSocket URL's components) は、 次のようにしなければなりません >>20

  1. 入力が絶対URLでなければ、失敗を返し、停止します。
  2. 入力についてURLの解決を行います。URL文字符号化は、 UTF-8 とします。 基底URLは何でも構いません。
  3. 解決結果の URL schemewswss でなければ、失敗を返し、停止します。
  4. 解決結果に素片識別子があれば、失敗を返し、停止します。
  5. secure を、URL schemewss ならws ならに設定します。
  6. ホストを、解決結果のホストに設定します。
  7. 解決結果に空文字列以外のポートがあれば、
    1. ポートを、指定されたポートに設定します。
  8. それ以外なら、
    1. ポートを、secureなら 443、そうでないなら 80 に設定します。
  9. 資源名に、解決結果のパスを設定します。ただし空文字列なら、 / に設定します。
  10. 解決結果に URL query があるなら、資源名の末尾に ?query を追加します。
  11. ホストポート資源名secure を返します。

比較

[18] ホストPunycode により表現するのとパーセント符号化により表現するのは等価です >>17

HTTP URL への変換

[32] fetch は、 WebSocket の処理の場合、 URL schemeWebSocket のものから HTTP のものに書き換えます。 各種仕様URL に基づく操作は書き換え後の状態で適用されます。

[33] 従って HSTSMixed ContentUpgrade-Insecure-Requests などは、 HTTP のみならず WebSocket にも同様の形で適用されます。

[30] RFC 時代は、 HTTP URLWebSocket URL の関係性が曖昧でした。

[16] WebSocket接続の確立は、相当する http:/https: URL を使うことがあります。これは ws:/wss: にそれぞれ相当するものと思われますが、明記はされていません。

[31] HSTSWebSocket に適用されるのかどうかも曖昧でした。

歴史

[26] Fix #244: improve HSTS language · whatwg/fetch@6568ab8 ( 版) <https://github.com/whatwg/fetch/commit/6568ab88c1fbfb581f63f8e5f020c367ef38e78d>

[27] Update WebSocket to use Fetch's WebSocket alterations · whatwg/html@3dadbca ( 版) <https://github.com/whatwg/html/commit/3dadbcad063a10b586ef52dd4b427aa339048ee7>