检查WebSocket是否是hixie客户端?

Luk*_*uke 2 javascript safari browser-detection websocket

根据维基百科,大多数浏览器使用RFC6455或稍早的版本具有几乎相同的握手.我正在使用的服务器仅支持RFC6455或类似,它接受Origin:Sec-WebSocket-Origin:取决于指定的版本.

Safari 5和iOS 5使用的是hixie版本WebSocket.如果WebSocket失踪,我通常会回到长轮询.Safari 5有一个WebSocket对象,但握手却截然不同.

有没有办法检测是否WebSocket是hixie,或属于Safari 5,所以我可以忽略它而不尝试握手?是否有任何方法可以在不依赖用户代理的情况下检查浏览器是否为Safari 5?

Luk*_*uke 6

根据WebSocket的W3C草案在2009年CLOSED常数具有2的值:

[Constructor(in DOMString url, in optional DOMString protocol)]
interface WebSocket {
  ...
  // ready state
  const unsigned short CONNECTING = 0;
  const unsigned short OPEN = 1;
  const unsigned short CLOSED = 2;
  ...
};
WebSocket implements EventTarget;
Run Code Online (Sandbox Code Playgroud)

2011 年的W3C草案中,CLOSED值为3:

[Constructor(in DOMString url, in optional DOMString protocols)]
[Constructor(in DOMString url, in optional DOMString[] protocols)]
interface WebSocket {
  ...
  // ready state
  const unsigned short CONNECTING = 0;
  const unsigned short OPEN = 1;
  const unsigned short CLOSING = 2;
  const unsigned short CLOSED = 3;
  ...
};
Run Code Online (Sandbox Code Playgroud)

2009年的草案对应于hixie/hibi-00,而2011年的草案对应于hibi-07及更高版本,如维基百科图表所示.

有了这些信息,您可以像这样进行JavaScript检查:

if("WebSocket" in window && WebSocket.CLOSED > 2) {
    // hibi-07 to RFC6455
} else {
    // No WebSocket, or hixie
}
Run Code Online (Sandbox Code Playgroud)

我在浏览器屏幕截图服务上使用了以下测试页面:

<html>
<body>
<div id="test"></div>
<script>
var test = document.getElementById("test");
var text = "no soup for you!";
if ("WebSocket" in window) {
    text = "WebSocket " + WebSocket.CLOSED;
} else if("MozWebSocket" in window) {
    text = "MozWebSocket " + MozWebSocket.CLOSED;
}
test.appendChild(document.createTextNode(text));
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

Safari 5和Chrome 12及以下版本返回2,而Safari 6和Chrome 14及以上版本则返回3 CLOSED.

Chrome 13 使用hixie,但返回3.这是我能找到的唯一边缘情况.自Chrome自动更新以来,Chrome 13用户应为零.

注意:这些常量在WebSocket构造函数和WebSocket.prototype上都设置.5.1之前的Safari 5.0仅在WebSocket.prototype上设置这些常量.如果您只打算支持RFC6455及更高版本,WebSocket.CLOSED > 2或者WebSocket.CLOSED === 3已足够.

  • 我们正在使用类似的测试,并且最近意识到某些版本的Safari(当然是5.0.1)在`WebSocket.prototype`上有`CLOSED`属性,而不是'WebSocket`.因此我们的测试更像是`if(window.WebSocket &&(WebSocket.CLOSED == 2 || WebSocket.prototype.CLOSED == 2)`. (3认同)