# 擴展
WebSocket客戶端可以請求本規范的擴展,且WebSocket服務器可以接受一些或所有客戶端請求的擴展。服務器不必響應不是客戶端請求的任何擴展。如果擴展參數包含在客戶端和服務器之間的協商中,這些參數必須按照參數應用到的擴展規范來選擇。
## [](https://github.com/zhangkaitao/websocket-protocol/wiki/9.%E6%89%A9%E5%B1%95#91%E5%8D%8F%E5%95%86%E6%89%A9%E5%B1%95)9.1.協商擴展
客戶端通過包含一個|Sec-WebSocket-Extensions|頭字段請求擴展,其按照正常的HTTP頭字段規則(參考[[RFC2616](http://www.faqs.org/rfcs/rfc2616.html)], 4.2節)并且頭字段的值按照以下ABNF定義[[RFC2616](http://www.faqs.org/rfcs/rfc2616.html)]。注意本章使用的ABNF語法/規則來源于[[RFC2616](http://www.faqs.org/rfcs/rfc2616.html)],包括“隱式的 *LWS規范”。如果客戶端或服務器在協商階段接收到的值不符合下邊的ABNF,這種畸形數據的接收人必須立即*失敗WebSocket連接*。
~~~
Sec-WebSocket-Extensions = extension-list
extension-list = 1#extension
extension = extension-token *( ";" extension-param )
extension-token = registered-token
registered-token = token
extension-param = token [ "=" (token | quoted-string) ]
;當使用引用字符串的語法變種時,引用字符串之后的值必須
;符合’token’ABNF
~~~
注意,像其他HTTP頭字段,這個頭字段可以跨多個行分割或組合,因此,以下是等價的:
~~~
Sec-WebSocket-Extensions: foo
Sec-WebSocket-Extensions: bar; baz=2
~~~
完全等價于
~~~
Sec-WebSocket-Extensions: foo, bar; baz=2
~~~
所有使用的extension-token必須是一個egistered token(參考11.4節)。任何給定擴展提供的參數必須被擴展定義。注意,客戶端只需提供使用任何公布的擴展,除非服務器表示它希望使用使用擴展,否則必須使用它們。
注意,擴展的順序是重要的。在多個擴展間的相互作用可以定義在定義擴展的文檔中。在沒有這樣定義的情況下,解釋是它請求中的客戶端列出的頭字段表示一個它希望使用的頭字段的偏好,第一個列出的選項是最優選的。服務器在響應中列出的擴展表示擴展是實際正在用于連接的擴展。擴展應該修改數據和/或組幀,數據的操作順序應該假定是與打開階段握手期間服務器響應中列出的擴展順序是一樣的。
例如,如果有兩個擴展“foo”和“bar”,且如果服務器發送的頭字段|Sec-WebSocket-Extensions|有值“foo”、“bar”,那么數據上的操作將變為bar(foo(data)),是更改數據本身(如壓縮)或更改可能“堆疊(stack)”的組幀。
可接受的擴展頭字段(注意:為了可讀性,將折疊較長行)的非規范化例子:
~~~
Sec-WebSocket-Extensions: deflate-stream
Sec-WebSocket-Extensions: mux; max-channels=4; flow-control,
deflate-stream
Sec-WebSocket-Extensions: private-extension
~~~
服務器通過包含一個容納了一個或多個擴展的客戶端請求的|Sec-WebSocket-Extensions|頭字段來接受一個或多個擴展。所有擴展參數的解釋,和什么構成一個有效的到客戶請求的參數集的服務器響應,將由各個擴展定義。
## [](https://github.com/zhangkaitao/websocket-protocol/wiki/9.%E6%89%A9%E5%B1%95#92%E5%B7%B2%E7%9F%A5%E6%89%A9%E5%B1%95)9.2.已知擴展
擴展提供了一種機制來實現選擇性加入的附加協議特性。本文檔沒有定義任何擴展,但實現可以使用單獨定義的擴展。