微信小程序真机调试连接mqtt失败原因及修复(EMQX客户端)
先说解决方案,在emqx配置文件中加一行配置然后重启emqx: listeners.ws.default.websocket.fail_if_no_subprotocol = false (虽然配置文件看起来像json,但你放心,就这么加就行)。(配置文件路径参考:https://www.emqx.io/docs/zh/v5.0/configuration/configuration.html)
现象:微信小程序开发在开发者工具里可以正常连接MQTT,但是真机调试时连接mqtt会报fail(不是https、wss这种弱智原因):
通过观察nginx日志发现,nginx返回400错误:
通过百度关键词: "GET /mqtt HTTP/1.1" 400 ,找到一篇文章:
https://blog.csdn.net/c519299013/article/details/127624143。里面说:
模拟器调试的时候存在sec-websocket-protocol:mqtt,而真机上不存在
然后搜 sec-websocket-protocol 到底为何物,简单来说就是规定了ws握手期间可使用的子协议,属于可选配置。(见:https://zhuanlan.zhihu.com/p/407711596?utm_id=0)
在nginx配置文件中尝试添加 Sec-WebSocket-Protocol 头,启动nginx报错。
于是想到修改emqx,找到官方文档:https://www.emqx.io/docs/zh/v5.0
在官方文档搜索“小程序”,果然找到一个关键:
ws_opts.fail_if_no_subprotocol
类型:
boolean
默认值:
true
如果
true
,当客户端未携带Sec WebSocket Protocol
字段时,服务器将返回一个错误。
注意:微信小程序需要禁用此验证。
OK,那么就是改配置了,官方文档目录中正好上一节就是“配置文件简介”,找到配置文件,加上 ws_opts.fail_if_no_subprotocol = false ,重启emqx,无效!!
然后在配置文件夹使用 find . -name "*.conf" | xargs grep "fail_if_no_subprotocol" --color=always 搜索,找到一个配置文件 emqx-example.conf ,
观察发现真实配置应该是
listeners.ws.$name.websocket.fail_if_no_subprotocol = false
对比 emqx.conf ,发现name可以写为default,于是最终修改为:
listeners.ws.default.websocket.fail_if_no_subprotocol = false
关于配置文件语法,虽然文件里是类json格式,但是也可以写成小数点分割形式,具体可以看官方介绍:https://www.emqx.io/docs/zh/v5.0/configuration/configuration.html
最后,上一个真机调试成功的截图,没有 Sec-WebSocket-Protocol :