Pour tester MQTT sur WebSockets, vérifiez la connexion en deux étapes : d'abord l'upgrade HTTP (bonne URL, bon chemin, sous-protocole mqtt, 101 Switching Protocols), puis une vraie session MQTT dans le socket (CONNECT, CONNACK, publish, subscribe). La plupart des problèmes WebSocket — 404, sockets fermés, blocages pour contenu mixte — surviennent à la première étape, avant même que MQTT n'entre en jeu.
Les exemples utilisent broker.connectmq.com : ws:// sur le port 8083 et wss:// sur le port 8084, tous deux avec le chemin /mqtt.
À quoi ressemble une connexion MQTT WebSocket fonctionnelle
Une URL MQTT WebSocket comporte quatre parties, et chacune peut être fausse :
| Partie | Exemple | Erreur typique |
|---|---|---|
| Schéma | wss:// | ws:// depuis une page HTTPS (bloqué comme contenu mixte) |
| Hôte | broker.connectmq.com | Adresse IP avec wss — le certificat ne correspond pas |
| Port | 8084 | Utiliser le port TCP 1883 ou le port TLS 8883 |
| Chemin | /mqtt | Chemin absent ou erroné — 404 Not Found |
Le client envoie aussi l'en-tête Sec-WebSocket-Protocol: mqtt. Le broker doit répondre par HTTP/1.1 101 Switching Protocols et renvoyer Sec-WebSocket-Protocol: mqtt. Ensuite, le socket transporte des paquets MQTT binaires ordinaires — les mêmes CONNECT et CONNACK qu'en TCP. Pour le contexte, voir MQTT sur WebSockets.
Étape 1 : tester le handshake
Avec curl
curl peut envoyer la requête d'upgrade à la main et afficher la réponse brute. Cela isole la partie HTTP de toute bibliothèque MQTT :
curl -i --http1.1 --max-time 5 \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
-H "Sec-WebSocket-Protocol: mqtt" \
https://broker.connectmq.com:8084/mqttUtilisez http://...:8083/mqtt pour tester le listener non chiffré. Un endpoint sain répond :
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: mqttcurl attend ensuite jusqu'à --max-time, car le socket reste ouvert — c'est normal. Les autres réponses vous indiquent quoi corriger :
| Réponse | Signification |
|---|---|
101 sans Sec-WebSocket-Protocol: mqtt | Le broker ou le proxy supprime le sous-protocole ; les navigateurs fermeront le socket |
404 Not Found | Mauvais chemin — essayez /mqtt, / ou le chemin documenté de votre broker (détails) |
400 Bad Request / 426 Upgrade Required | En-têtes d'upgrade manquants — souvent un proxy qui ne les transmet pas |
502 Bad Gateway | Le reverse proxy n'atteint pas le listener WebSocket du broker |
Empty reply from server ou reset | Le port parle MQTT/TLS classique, pas WebSocket |
| Erreur de certificat SSL | Les mêmes problèmes TLS que sur 8883 — le certificat doit correspondre au nom d'hôte |
Si le broker se trouve derrière Nginx ou un autre proxy, un 400 ou un sous-protocole absent signifient presque toujours que les en-têtes Upgrade et Connection ne sont pas transmis — voir MQTT derrière un proxy Nginx.
Avec wscat
wscat est un petit client WebSocket qui négocie correctement le sous-protocole :
npx wscat -c wss://broker.connectmq.com:8084/mqtt -s mqttConnected (press CTRL+C to quit) signifie que le handshake et le sous-protocole sont corrects. Quelques secondes plus tard, le broker ferme le socket, car aucun paquet MQTT CONNECT n'est arrivé — c'est normal et cela confirme même qu'un broker MQTT écoute. Sans -s mqtt, beaucoup de brokers refusent l'upgrade, ce qui constitue un test négatif utile.
Étape 2 : tester une vraie session MQTT
Les clients en ligne de commande de mosquitto ne savent pas se connecter en WebSockets ; utilisez donc un client compatible. Le plus rapide est le client MQTT en ligne : saisissez l'URL wss://, connectez-vous, abonnez-vous à un topic de test et publiez dessus. Si cela fonctionne, le côté broker est correct et tout problème restant se trouve dans votre application.
Pour une vérification automatisée, ce script MQTT.js 5 tourne dans Node.js ou, presque sans changement, dans le navigateur :
import mqtt from "mqtt";
const url = "wss://broker.connectmq.com:8084/mqtt";
const topic = `testmqtt/ws/${Math.random().toString(16).slice(2, 10)}`;
const client = mqtt.connect(url, {
protocolVersion: 5,
username: process.env.MQTT_USER,
password: process.env.MQTT_PASS,
connectTimeout: 5000,
reconnectPeriod: 0, // échouer vite pendant le test
});
const started = Date.now();
client.on("connect", (connack) => {
console.log(`CONNACK reason ${connack.reasonCode ?? 0} after ${Date.now() - started} ms`);
client.subscribe(topic, { qos: 1 }, () => client.publish(topic, "ping over websocket", { qos: 1 }));
});
client.on("message", (t, payload) => {
console.log(`round trip ok on ${t}: ${payload}`);
client.end();
});
client.on("error", (err) => { console.error("error:", err.message); process.exit(1); });
client.on("close", () => console.log("socket closed"));MQTT.js définit automatiquement le sous-protocole mqtt. Python fonctionne aussi — paho-mqtt 2.x avec transport="websockets" :
import os
import paho.mqtt.client as mqtt
c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, transport="websockets", protocol=mqtt.MQTTv5)
c.ws_set_options(path="/mqtt")
c.tls_set() # à retirer pour ws:// sur le port 8083
c.username_pw_set(os.environ["MQTT_USER"], os.environ["MQTT_PASS"])
c.on_connect = lambda cl, u, f, rc, p: print("CONNACK:", rc)
c.connect("broker.connectmq.com", 8084)
c.loop_forever()Le chemin WebSocket par défaut de paho est déjà /mqtt, donc ws_set_options est facultatif ici — mais les brokers qui utilisent / ou un chemin personnalisé répondent par un 404 tant que vous ne le définissez pas explicitement.
Déboguer avec les DevTools du navigateur
Quand une application web n'arrive pas à se connecter, le navigateur vous montre chaque détail du handshake :
- Ouvrez les DevTools → Network, filtrez sur WS (Chrome) ou choisissez WS dans le filtre de type (Firefox), puis rechargez la page.
- Cliquez sur la requête du socket. Dans Headers, vérifiez le statut (
101), l'URL et le chemin, et que la requête comme la réponse contiennentSec-WebSocket-Protocol: mqtt. - Ouvrez l'onglet Messages (Chrome) ou Response (Firefox). La première trame sortante est le CONNECT MQTT binaire ; la première trame entrante est le CONNACK. Si le CONNECT part et que le socket se ferme sans CONNACK, le broker a refusé la session MQTT (identifiants, client ID), pas le WebSocket.
- Cherchez dans la Console des erreurs comme celles-ci :
WebSocket connection to 'wss://broker.example.com:8084/mqtt' failed:
Mixed Content: The page at 'https://app.example.com/' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://broker.example.com:8083/mqtt'. This request has been blocked; this endpoint must be available over WSS.La première, sans rien après les deux-points, est l'échec générique du navigateur — en général un mauvais port, un mauvais chemin ou un problème de certificat ; consultez l'onglet Network. La seconde ne se corrige qu'en passant à wss:// (contenu mixte). Un code de fermeture 1006 signifie que la connexion a été coupée sans trame de fermeture correcte, souvent à cause d'un timeout de proxy ou d'un broker qui refuse la connexion. Pour la liste complète des causes, voir MQTT WebSocket connection failed.
Checklist des tests WebSocket
- curl sur l'URL
wss://renvoie101et retourneSec-WebSocket-Protocol: mqtt. - wscat avec
-s mqttse connecte ; sans, le broker refuse ou ferme. - Un vrai client reçoit un CONNACK et réalise un aller-retour publish/subscribe.
- Le navigateur se connecte depuis une page HTTPS en
wss://, sans erreur dans la console. - À travers votre proxy ou load balancer, les connexions inactives survivent plus longtemps que l'intervalle de keep-alive.
- Les identifiants et les ACL se comportent de la même façon sur le listener WebSocket que sur TCP.
Testez l'endpoint WebSocket dans votre navigateur
Les problèmes WebSocket ne paraissent mystérieux que tant qu'on ne les coupe pas en deux. Validez l'upgrade HTTP avec curl ou wscat, puis la session MQTT avec un vrai client, et vous saurez en quelques minutes s'il faut corriger l'URL, le proxy ou les identifiants MQTT.
Questions fréquentes
Quel est le chemin WebSocket de MQTT ?
Il n'existe pas de standard unique. /mqtt est le plus courant (EMQX, HiveMQ et ConnectMQ l'utilisent, et les proxys placés devant Mosquitto le routent généralement), mais certains brokers écoutent sur / ou sur un chemin personnalisé. Un mauvais chemin renvoie généralement HTTP 404 pendant le handshake.
Quel sous-protocole WebSocket MQTT utilise-t-il ?
mqtt, pour MQTT 3.1.1 comme pour MQTT 5. Les anciens clients MQTT 3.1 utilisaient mqttv3.1. Le client l'envoie dans Sec-WebSocket-Protocol et le broker doit le renvoyer dans la réponse 101 ; sinon, les navigateurs coupent la connexion.
mosquitto_pub peut-il se connecter en WebSockets ?
Non. Les clients en ligne de commande de mosquitto ne parlent MQTT qu'en TCP et TLS. Pour tester un listener WebSocket, utilisez un client dans le navigateur, MQTT.js, paho-mqtt avec transport="websockets" ou un client desktop comme MQTTX.


