メッセージ毎圧縮

メッセージ毎圧縮

[50] WebSocket接続の確立時にクライアントサーバーSec-WebSocket-Extensions: ヘッダーにより折衝することで、 拡張 (extension) を使うことができます。

[68] 拡張圧縮 permessage-deflate のために用いられています。 理論上はそれ以外の用途や手法にも利用できますが、実際には使われていません。

仕様書

拡張

[78] 拡張は、 WebSocket プロトコル本体仕様に含まれない機能を追加で定めるものです。

[80] WebSocket の実装はどの拡張にも対応する義務はありません。 クライアントサーバーはどの拡張を利用するかを WebSocket接続の確立時に決定します。

[81] 実際に存在しているのは PMCE のみです。

PMCE

[55] RFC 7692WebSocket圧縮機能を追加するフレームワークとして WebSocket Per-Message Compression Extensions (PMCEs) を定義しています。 >>54

[56] RFC 7692PMCE に則った具体的な WebSocket拡張として permessage-deflate を定義しています。これ以外は定義されていませんし、 その動きもありません。

[77]PMCE は、次のものを定めなければなりません >>76

クライアント API

[65] JavaScriptWebSocket クライアントが利用する拡張を指定する手段は提供されていません。 どの拡張を使うかは、 Webブラウザーの実装次第となっています。

WebSocket インターフェイス extensions 属性

[34] WebSocket インターフェイスextensions IDL属性は、 利用されている拡張について返すものです。

[66] このIDL属性により、クライアントサーバーとの折衝の結果利用されることとなった (そして現に利用されている) 拡張が何であるかを著者は知ることができます。

[67] もっとも、この情報が有用かどうかは謎です。

[35] この属性は、内部的に保持している値を返さなければなりません >>33。 値は、WebIDL接続の確立の過程で設定されます。

ハンドシェイク

[4] ハンドシェイクの手順についてはWebSocket接続の確立を参照。

Sec-WebSockete-Extensions: ヘッダー

[3] クライアントSec-WebSocket-Extensions: ヘッダー拡張を指定することで、 拡張を使うことを要求できます。

[64] サーバーSec-WebSocket-Extensions: ヘッダー拡張を指定することで、 拡張を使うことに合意することを示せます。


[5]ヘッダーの値は、 1つ以上拡張の指定のリスト (HTTP) (#) です >>2

  1. 拡張の指定
  2. *
    1. OWS
    2. ,
    3. OWS
    4. 拡張の指定

[12] 拡張の指定の順序は、意味を持ちます。 拡張同士の関係は、 特に規定がある場合は、それによります。そうでない場合、 クライアントが先に指定したものが優先度の高いものです。 サーバーが指定した順序が実際の適用順となり、 データに対して先に指定したものから順に拡張依存の操作を適用していったことを表します。 >>2

[57] next extension in use after extension X とは、 サーバーSec-WebSocket-Extensions: ヘッダーX の直後に指定した拡張です。 すなわち、送信するデータに関しては X の直後に適用し、 受信するデータに関しては X の直前に適用するものです。 >>75

[58] extension in use preceding extension X とは、 サーバーSec-WebSocket-Extensions: ヘッダーX の直前に指定した拡張です。 すなわち、送信するデータに関しては X の直前に適用し、 受信するデータに関しては X の直後に適用するものです。 >>75


[6] 拡張の指定は、 拡張字句の後に0個以上の引数を続けたものです。 引数の前には ; が必要です。 >>2 暗示的な空白 >>2 により、 ; の前後には OWS が認められると推測されます。

[9] 字句は、IANA登録簿 >>15, >>17 に登録されたものでなければなりません >>2

  1. 字句
  2. *
    1. OWS
    2. ;
    3. OWS
    4. 引数

[7] 引数は、字句の後に = があり、 その後に字句引用文字列が来るものです。ただし = 以後は省略できます。また引用文字列の場合は、 unescape して字句となる値でなければなりません>>2 暗示的な空白 >>2 により、 ; の前後には BWS が認められると推測されます。

[10] 引数は、当該拡張で定義されたものでなければなりません >>2

  1. 字句
  2. ?
    1. =
    2. |
      1. 字句
      2. 引用文字列

[8]ヘッダーは、要求では複数指定できます >>2, >>14応答で複数使ってはならない >>14 と規定がありますが、 他の部分と矛盾しているとし、使っても良いと訂正 >>16 されています。


[11] クライアントは、サーバー応答で同意しない限り拡張を使ってはなりません >>2

処理

[59] extension negotiation offer は、クライアントSec-WebSocket-Extensions: ヘッダーの各要素です。 >>75

[83] クライアントは、 PMCE を使うことを望む場合、 Sec-WebSocket-Extensions: ヘッダーPMCE 拡張名を含めなければなりません。 必要があれば引数も使います。 >>82

[84] 複数の PMCE を指定したり、異なる引数の同じ PMCE を複数指定したりもできます。 >>82

[85] 順序は、クライアントの希望の高い順とします。 サーバーは、対応している希望度の高いものを採用するべき (recommended) です。 >>82

[86] PMCE extension negotiation offer は、 クライアントからサーバーに対する要求 (request) ヒント (hint) を記述するものです。 要求は、サーバーが満たさなければならない制約を指定するものです。 ヒントは、サーバーが無視しても採用しても良いクライアントの動作に関する情報を記述するものです。 >>82

[98] クライアントは offer の引数で次のような情報を記述します。 サーバーはこれを元に動作を決定します。 >>82

  • クライアントがデータを圧縮する方法のヒント
  • サーバーが圧縮する方法の要求
  • クライアントの圧縮機能についての制限

[60] extension negotiation response は、サーバーSec-WebSocket-Extensions: ヘッダーの各要素です。 >>75

[61] corresponding extension negotiation response for an extension negotiation offer は、 extension negotiation offer と同じ拡張名であってその表す要件を満たす extension negotiation response です。 >>75

[62] Accepting an extension negotiation offer とは、 corresponding extension negotiation response for an extension negotiation offer を含めることです。 >>75

[63] Declining an extension negotiation offer とは、 corresponding extension negotiation response for an extension negotiation offer を含めないことです。 >>75

[87] サーバーは、 PMCE の offer を accept する場合、 拡張名を Sec-WebSocket-Extensions: ヘッダーに含めなければなりません引数PMCE の詳細を記述するもので、 agreed parameter といいます。 この extension negotiation response は、 サーバーが完全に対応している PMCE でなければなりません>>82

[99] サーバー引数で次の事項を記述します。 クライアントはこれにより動作を決定します。 >>82

  • クライアントがデータを圧縮する方法についての要求
  • サーバーがデータを圧縮する方法

[89] agreed parameter は、 クライアントの要求とヒントをサーバーがどう扱うかを表すものであると共に、 サーバークライアントの挙動について要求とヒントを示すものでもなければなりません。 >>82

[88] extension negotiation responseextension negotiation offer と完全に一致している必要はありません。 offer の引数で指定された追加機能をサーバーが使わない場合は、 これを agreed parameter に含めないようにします。 なお extension negotiation offer の引数名と extension negotiation response の引数名が同じである必要もありません。 >>82

[90] 引数名は送受信どちらに関するものであるかを区別するため server_client_ をつけることもできます。 >>82

[91] サーバーは、 PMCE extension negotiation offerRSV1 の用法が衝突する他の拡張を同時に受理してはなりませんクライアントは、そのような応答を受信した場合、 WebSocket接続失敗としなければなりません>>82

[92] サーバーは、PMCE が出力に適用される場合に、 次のような状況となるような他の拡張を同時に受理してはなりませんクライアントは、そのような応答を受信した場合、 WebSocket接続失敗としなければなりません>>82

[95] サーバーは、 PMCE をすべて declining する場合には、 PMCE 拡張名を含めてはなりません>>82

[96] クライアントが offer していない PMCE が accepting されているなど不当な応答を受信した場合には、 クライアントWebSocket接続失敗としなければなりません>>82

[100] クライアントPMCE extension negotiation response が受け入れられないものである時は、 閉じ符号 1010closing handshake を開始します。 >>82

[97] サーバーが妥当な PMCE の指定を Sec-WebSocket-Extensions: ヘッダーに含め、 WebSocket接続確立に至った場合、 クライアントサーバーagreed parameter に従った PMCE により、 message payload の変形 (圧縮・展開) を行わなければなりません>>82

フレーム

[52] 拡張は、次のプロトコル要素を使うことができます >>49

[79] 拡張の利用可能なプロトコル要素

拡張データ

[103] WebSocketフレームには、 拡張データ (extension data) 欄があります。 これは拡張により規定された長さと用途のデータです。 拡張がなければ長さ 0 です。 >>102

[13] 現時点で利用例はありません。

RSV1、RSV2、RSV3

[101] WebSocketフレームには、 RSV1 (frame-rsv1), RSV2 (frame-rsv2), RSV3 (frame-rsv3) の3つの1ビット欄があります。 >>102

[108] この3つの欄は、拡張により規定される場合を除き、 0 でなければなりません。 受信したフレームのこの3つの欄のいずれかであっても非 0 値であり、拡張の規定に拠っていない場合には、 WebSocket接続失敗としなければなりません>>102

[109] この3つの欄についてはIANA登録簿があります >>163, >>166permessage-deflate における RSV1 が登録されています。

[104] PMCERSV1メッセージ毎圧縮 (Per-Message Compressed) ビットと呼んでいます。 メッセージ圧縮されているか否かを表します。 >>111

[120] データメッセージの先頭のデータフレームメッセージ毎圧縮ビットが設定されている場合、 そのデータメッセージpayloadデータは圧縮データです。

[119] 制御フレームや、データメッセージの先頭以外のデータフレームでは、 メッセージ毎圧縮ビットを設定してはなりません。 そのようなフレームを受信した場合、 WebSocket接続失敗としなければなりません>>111

PMCE

[110] PMCEデータメッセージにのみ適用されます。 >>111

[105] 最初のフレームメッセージ毎圧縮ビットの設定されたメッセージを、 圧縮メッセージ (compressed message) といいます。 >>111

[122] 圧縮メッセージフレームpayloadデータは、 圧縮されたデータです。 opcode 依存の payloadデータの制約は、展開された状態のデータにのみ適用されます。 >>111

[123] 例えばテキストフレームからはじまる message payloadUTF-8 データでなければなりません。圧縮メッセージでは実際に送信される各フレームpayloadデータUTF-8 になっているとは限りません (なっていない可能性の方が高いです)。 しかしそれを展開した結果は UTF-8 となっていなければなりません。

[106] 最初のフレームメッセージ毎圧縮ビットの設定されていないメッセージを、 非圧縮メッセージ (uncompressed message) といいます。 >>111

[121] 非圧縮メッセージフレームpayloadデータは、 圧縮されていないデータです。 >>111

[107] メッセージの送信時には、 次のようにしなければなりません >>111

  1. [115] 圧縮メッセージの場合、
    1. [112] データを、 message payloadPMCE圧縮を適用した結果に設定します。
    2. [113] データを使ってフレーム(群)を生成します。
    3. [114] 最初のフレームメッセージ毎圧縮を、 1 に設定します。
  2. [116] 非圧縮メッセージの場合、
    1. [117] データを、 message payload に設定します。
    2. [118] データを使ってフレーム(群)を生成します。

[124] 圧縮メッセージを受信した場合、 次のようにしなければなりません>>111

  1. [128] メッセージ毎圧縮1 の場合、
    1. [125] データを、圧縮メッセージフレームpayloadデータを連結したものに設定します。
    2. [126] データを、データPMCE展開を適用した結果に設定します。
    3. [127] メッセージ毎圧縮を、0 に設定します。

permessage-deflate

[130] DEFLATE を使う場合の拡張名は permessage-deflate です。 次の引数があります。 いずれもクライアントextension negotiation offerサーバーextension negotiation response で使用します。 >>129

[131] permessage-deflate引数

[132] client_クライアントが圧縮しサーバーが展開する際のもの、 server_サーバーが圧縮しクライアントが展開する際のものを表します。 >>129

[133] サーバーは、 次のいずれかを満たす場合、 extension negotiation offer を decline しなければなりません>>129

[134] クライアントは、 extension negotiation offer に対する extension negotiation response が次のいずれかを満たす場合、 WebSocket接続失敗としなければなりません>>129

実装

[74] ChromeFirefoxpermessage-deflate を実装しています。

歴史

拡張の一覧

[18] 現時点で IANA に登録されている拡張はありません。

[48] 2015年9月に permessage-deflate が登録されています。

[23] DEFLATE 圧縮のための x-webkit-deflate-frame が実装されていました >>20

[24] その改訂版である permessage-deflate >>46 が実装されています >>25, >>22

[29] Chrome は次のようなヘッダーを送るようです。

Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits, x-webkit-deflate-frame

[39] Chrome は現在は次のようなヘッダーを送るようです。
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits

[31] 他に多重化のための拡張が提案されていました >>30

メモ

[43] 拡張のせいで不必要にプロトコルが複雑になっている気がしますが...

[41] WebSocket permessage-deflate in Chrome with no context takeover - Stack Overflow ( 版) <http://stackoverflow.com/questions/22169036/websocket-permessage-deflate-in-chrome-with-no-context-takeover>

[42] Intent to Implement: PerMessageDeflate extension on WebSocket - Google グループ ( 版) <https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/ZboxIILY2fo>

[44] Issue 163882 - chromium - WebSocket permessage-deflate: Improve compress/no-compress decision - An open-source project to help move the web forward. - Google Project Hosting ( 版) <https://code.google.com/p/chromium/issues/detail?id=163882>

[45] Re: [hybi] Closing the hybi working group ( 版) <http://www.ietf.org/mail-archive/web/hybi/current/msg10527.html>

[47] [hybi] Discontinuation of mux standardizaton in favor of WS/HTTP/2.0 ( 版) <http://www.ietf.org/mail-archive/web/hybi/current/msg10266.html>

[51] Define permessage-deflate extension and cache-mode for WebSocket · whatwg/fetch@267a8ef ( 版) <https://github.com/whatwg/fetch/commit/267a8effeacfe5d641010d1d4f4609f9602cdab6>

[53] Fix #852: WebSocket has implemented extensions · whatwg/html@78e6d56 ( 版) <https://github.com/whatwg/html/commit/78e6d56a64eb7d8ed7ee29b93ea37789f249b3ef>

[69] Bug 485469 – permessage-deflate extension causes protocol error in Firefox/Chrome () <https://bugs.eclipse.org/bugs/show_bug.cgi?id=485469>

[70] 580290 - permessage-deflate implementation does not support RFC7692 Section 7.2.3.6 (empty frame) correctly - chromium - Monorail () <https://bugs.chromium.org/p/chromium/issues/detail?id=580290>

[71] 115504 – [WebSocket] Remove x-webkit-deflate-frame extension support () <https://bugs.webkit.org/show_bug.cgi?id=115504>

[72] 98840 – [WebSocket] Add permessage-compress extension () <https://bugs.webkit.org/show_bug.cgi?id=98840>

[73] 115863 – [WebSocket] Update pywebsocket to r760 () <https://bugs.webkit.org/show_bug.cgi?id=115863>