toolfree

WebSocket 测试

从浏览器开一条 WebSocket,送出帧并看服务器回什么。直接连到你的服务器,所以 localhost 也连得上;1006 会解释而不是只印出来。

在你的浏览器中运行

已关闭
状态
协商出的子协议

收发记录

  1. 目前没有记录。

你的浏览器直接连到你输入的地址,不会经过本站——这也是为什么本机地址也连得上。

关闭代码

代码意义
1000Normal closure
1001Going away
1002Protocol error
1003Unsupported data
1005No status received服务器不会发送
1006Abnormal closure服务器不会发送
1007Invalid frame payload data
1008Policy violation
1009Message too big
1010Mandatory extension missing
1011Internal server error
1012Service restart
1013Try again later
1014Bad gateway
1015TLS handshake failed服务器不会发送

连线是你的浏览器发起的,不是本站

这条连线由你自己的浏览器直接连到你输入的地址,完全不经过本站。这件事有两个值得知道的后果:

关闭代码 1006——大多数人是为了它来的

1006 不是你的服务器说的话。你的服务器送不出这个码,规格明文禁止,10051015 也一样。 它是浏览器在「连线结束了,但没有收到关闭帧」时所报的,意思仅止于此:连线死了,而没有人说原因。

下面这串里的某一个,而 WebSocket API 不会告诉你是哪一个:

API 是刻意不给原因的。 一个网页不可以有能力分辨「连线被拒」和「路由不通」,因为这个差别足以 让网页扫描访客的内网。不是浏览器知道却不给你,是浏览器刻意不往上传。

真正的错误通常在浏览器自己的控制台里,而那个地方 JavaScript 碰不到。打开开发者工具,看 控制台和网络分页的 WS 标签,常常就能看到那次握手实际拿到的 HTTP 状态。

混合内容:在任何流量之前就失败

这个页面是以 HTTPS 提供的,而安全页面不允许开启纯 ws:// 连线。浏览器会在一个字节送出去之前 就挡下来——然后把它报成一般的连线失败,看起来跟服务器挂掉一模一样。

这个页面在开启连线之前就先检查,并直接把原因说出来。

localhost 是例外:浏览器把环回地址视为安全环境,所以从 HTTPS 页面用 ws:// 测本机开发服务器 是可以的。其他地址一律要 wss://

握手,以及代理服务器为什么会弄坏它

WebSocket 一开始是一个普通的 HTTP GET,带着 Upgrade: websocketConnection: Upgrade,只有 在服务器回 101 Switching Protocols 时才算成功。回任何其他状态码都到此为止。

几乎每一个「本机好好的、上线就烂掉」的 WebSocket 问题,都是反向代理把这两个头部吃掉了。nginx 需要明确把它们加回去:

location /ws/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 3600s;
}

proxy_http_version 1.1 这行是关键——默认是 1.0,而 1.0 根本没有 upgrade 机制。超时那行也是: nginx 默认 60 秒就会关掉闲置连线,症状是「连线一切正常,然后刚好一分钟后死掉」。

子协定

第二个选填栏位会送出 Sec-WebSocket-Protocol 头部,按偏好顺序提出一份清单。服务器挑一个回 给你,页面上会显示挑中的是哪一个。实务上会遇到的是 graphql-wsmqttjson

提出一个服务器没有回应的子协定,连线会直接死掉,而这一点很常让人卡住。服务器一个都不认得 时,它会照样完成握手、但不回这个头部——而 RFC 6455 接着要求客户端必须让这条连线失败。浏览器 就是这么做的,于是你拿到 1006,跟「服务器根本没开」拿到的是同一个码。

所以填了子协定就秒断、清空就连得上,那不是服务器坏了,是那台服务器不讲你指定的那个子协定。

你不能设头部,而这件事决定了验证怎么做

浏览器的 WebSocket API 只收一个网址和一份子协定清单,就这样。没有办法送出 Authorization 头部——这里不行,任何浏览器里都不行,换哪个库都不行。

所以服务器端的验证只能走别的路:

有些库看起来能从浏览器送 Authorization 头部。它们没有,它们是把它塞进第一个帧里。

关闭代码

上面的表格列出了全部。要记的是这个结构:

浏览器只被允许送出 1000 或 3000–4999 之间的代码。从这个页面按中断,送出的是 1000

相关

我的 IP 地址是你的服务器看到的东西, CSR 产生器处理 wss:// 背后那张证书, 帧收回来之后可以用 JSON 格式化读。