微信小程序使用STOMP(WebSocket)
小程序的WebSocket API跟一般浏览器的有点差别,存在一些限制。本文主要涉及小程序使用STOMP时注意事项。
基础
- 小程序需要维护两个状态:
- 微信服务器登录状态
- 第三方(即我们自己服务器)的登录状态
- 小程序使有wx.request()来发起请求,使用wx.connectSocket()创建WebSocket连接
- wx.request()不会自动加上cookie来,可以自己加cookie到header或使用其他session标识
- wx.connectSocket()跟wx.request()类似,handshake时加上session标识
- 真实环境需要在微信平台预设相关域名,必须使用TLS,即使用https、wss协议。开发调试时可以不限制。
使用STOMP与WebSocket遇到的问题
问题1: 连接成功后,很快自动断开
因为刚开始使用STOMP时,同事在网上找到以下代码。出现问题我打开代码看了一下,刚看到肯定都觉得两个空方法很奇怪,原来不写会报错。打开stomp.js一看,很快找到原因,setInterval是用来发心跳包的,而小程序没有window对象。
网络文章
var Stomp = require('../../utils/stomp.js').Stomp; Stomp.setInterval = function () { } Stomp.clearInterval = function () { } var client = Stomp.over(ws); 1 2 3 4
stomp.js部分源码
if (typeof window !== "undefined" && window !== null) { Stomp.setInterval = function (interval, f) { return window.setInterval(f, interval); }; Stomp.clearInterval = function (id) { return window.clearInterval(id); }; window.Stomp = Stomp; } else if (!exports) { self.Stomp = Stomp; } 1 2 3 4 5 6 7 8 9 10 11
解决办法
Stomp.setInterval = function (interval, f) { return setInterval(f, interval); }; Stomp.clearInterval = function (id) { return clearInterval(id); }; 1 2 3 4 5 6
问题2: 电脑开发时连接正常,手机远程调试时连接失败
一开始 返回 401 UNAUTHORIZED,后来看到client日志提示draft handshake refused。
逐步排除 域名限制、TLS证书有效性、Nginx配置、跨域问题。本应该先关注 401状态码的,通过服务器日志与后台调试,发现问题所在:client发起连接时没有在代码加上session标识,server需要它来验证的,所以握手时就失败。而在电脑开发时,websocket连接却自动带上了cookie,所以做成了手机与电脑的不一致。
解决办法,连接时加上session标识
wx.connectSocket({ url: 'wss://example.qq.com', header:{ 'Session-Id': 'xxxxxxxx' }, success(): function(){ // } }); 1 2 3 4 5 6 7 8 9
Nginx配置WebSocket反向代理
location /websocket { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } 1 2 3 4 5 6 7
另外,Nginx对外服务可以使用https,RealServer可以只用http
小程序websocket官方说明
基础库 1.7.0 之前,一个微信小程序同时只能有一个 WebSocket 连接,如果当前已存在一个 WebSocket 连接,会自动关闭该连接,并重新创建一个 WebSocket 连接。基础库版本 1.7.0 及以后,支持存在多个 WebSokcet 连接,每次成功调用 wx.connectSocket 会返回一个新的 SocketTask。— https://mp.weixin.qq.com
示例代码
wx.connectSocket({ url: 'wss://example.qq.com', data:{ x: '', y: '' }, header:{ 'content-type': 'application/json' }, protocols: ['protocol1'], method:"GET" })