Tests de brokers

Comment tester MQTT sur WebSockets (ws et wss)

Testez un endpoint MQTT WebSocket étape par étape : chemin /mqtt, sous-protocole mqtt, handshake avec curl et wscat, DevTools et un test MQTT.js.

Mis à jour · 8 min de lecture

Comment tester MQTT sur WebSockets (ws et wss)

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 :

PartieExempleErreur typique
Schémawss://ws:// depuis une page HTTPS (bloqué comme contenu mixte)
Hôtebroker.connectmq.comAdresse IP avec wss — le certificat ne correspond pas
Port8084Utiliser le port TCP 1883 ou le port TLS 8883
Chemin/mqttChemin 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 :

Vérification du handshake WebSocket
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/mqtt

Utilisez http://...:8083/mqtt pour tester le listener non chiffré. Un endpoint sain répond :

Réponse attendue
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: mqtt

curl attend ensuite jusqu'à --max-time, car le socket reste ouvert — c'est normal. Les autres réponses vous indiquent quoi corriger :

RéponseSignification
101 sans Sec-WebSocket-Protocol: mqttLe broker ou le proxy supprime le sous-protocole ; les navigateurs fermeront le socket
404 Not FoundMauvais chemin — essayez /mqtt, / ou le chemin documenté de votre broker (détails)
400 Bad Request / 426 Upgrade RequiredEn-têtes d'upgrade manquants — souvent un proxy qui ne les transmet pas
502 Bad GatewayLe reverse proxy n'atteint pas le listener WebSocket du broker
Empty reply from server ou resetLe port parle MQTT/TLS classique, pas WebSocket
Erreur de certificat SSLLes 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 :

wscat
npx wscat -c wss://broker.connectmq.com:8084/mqtt -s mqtt

Connected (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 :

ws-check.mjs (MQTT.js 5)
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" :

ws_check.py (paho-mqtt 2.x)
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 :

  1. Ouvrez les DevTools → Network, filtrez sur WS (Chrome) ou choisissez WS dans le filtre de type (Firefox), puis rechargez la page.
  2. 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 contiennent Sec-WebSocket-Protocol: mqtt.
  3. 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.
  4. Cherchez dans la Console des erreurs comme celles-ci :
Erreurs de console typiques
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

  1. curl sur l'URL wss:// renvoie 101 et retourne Sec-WebSocket-Protocol: mqtt.
  2. wscat avec -s mqtt se connecte ; sans, le broker refuse ou ferme.
  3. Un vrai client reçoit un CONNACK et réalise un aller-retour publish/subscribe.
  4. Le navigateur se connecte depuis une page HTTPS en wss://, sans erreur dans la console.
  5. À travers votre proxy ou load balancer, les connexions inactives survivent plus longtemps que l'intervalle de keep-alive.
  6. 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.