Testes de brokers

Como testar MQTT sobre WebSockets (ws e wss)

Teste um endpoint MQTT WebSocket passo a passo: o caminho /mqtt, o subprotocolo mqtt, checagens do handshake com curl e wscat, DevTools e um teste com MQTT.js.

Atualizado · 8 min de leitura

Como testar MQTT sobre WebSockets (ws e wss)

Para testar MQTT sobre WebSockets, verifique a conexão em duas etapas: primeiro o upgrade HTTP (URL certa, caminho certo, subprotocolo mqtt, 101 Switching Protocols), depois uma sessão MQTT real dentro do socket (CONNECT, CONNACK, publish, subscribe). A maioria dos problemas com WebSockets — 404, sockets fechados, bloqueios de conteúdo misto — acontece na primeira etapa, antes mesmo de o MQTT entrar em cena.

Os exemplos usam broker.connectmq.com: ws:// na porta 8083 e wss:// na porta 8084, ambos com o caminho /mqtt.

Como é uma conexão MQTT WebSocket funcionando

Uma URL MQTT WebSocket tem quatro partes, e qualquer uma pode estar errada:

ParteExemploErro típico
Esquemawss://ws:// a partir de uma página HTTPS (bloqueado como conteúdo misto)
Hostbroker.connectmq.comEndereço IP com wss — certificado não confere
Porta8084Usar a porta TCP 1883 ou a porta TLS 8883
Caminho/mqttCaminho ausente ou errado — 404 Not Found

O cliente também envia o cabeçalho Sec-WebSocket-Protocol: mqtt. O broker precisa responder com HTTP/1.1 101 Switching Protocols e devolver Sec-WebSocket-Protocol: mqtt. Depois disso, o socket transporta pacotes MQTT binários comuns — o mesmo CONNECT e CONNACK do TCP. Para o contexto, veja MQTT sobre WebSockets.

Etapa 1: teste o handshake

Com curl

O curl consegue enviar a requisição de upgrade manualmente e mostrar a resposta bruta. Isso isola a parte HTTP de qualquer biblioteca MQTT:

Verificação do 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

Use http://...:8083/mqtt para testar o listener sem criptografia. Um endpoint saudável responde:

Resposta esperada
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: mqtt

Depois o curl espera até o --max-time, porque o socket continua aberto — isso é esperado. Outras respostas dizem o que corrigir:

RespostaSignificado
101 sem Sec-WebSocket-Protocol: mqttO broker ou proxy descarta o subprotocolo; os navegadores vão fechar o socket
404 Not FoundCaminho errado — tente /mqtt, / ou o caminho documentado do seu broker (detalhes)
400 Bad Request / 426 Upgrade RequiredCabeçalhos de upgrade ausentes — muitas vezes um proxy que não os repassa
502 Bad GatewayO proxy reverso não alcança o listener WebSocket do broker
Empty reply from server ou resetA porta é MQTT/TLS comum, não WebSocket
Erro de certificado SSLOs mesmos problemas de TLS da 8883 — o certificado precisa bater com o hostname

Se o broker estiver atrás do Nginx ou de outro proxy, um 400 ou um subprotocolo ausente quase sempre significam que os cabeçalhos Upgrade e Connection não estão sendo repassados — veja MQTT atrás de um proxy Nginx.

Com wscat

O wscat é um pequeno cliente WebSocket que negocia o subprotocolo corretamente:

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

Connected (press CTRL+C to quit) significa que o handshake e o subprotocolo estão corretos. Alguns segundos depois o broker fecha o socket, porque nenhum pacote MQTT CONNECT chegou — isso é normal e, na verdade, confirma que há um broker MQTT escutando. Sem -s mqtt, muitos brokers recusam o upgrade, o que serve como teste negativo.

Etapa 2: teste uma sessão MQTT real

Os clientes de linha de comando do mosquitto não conectam via WebSockets, então use um cliente compatível. O mais rápido é o cliente MQTT online: informe a URL wss://, conecte, assine um tópico de teste e publique nele. Se funcionar, o lado do broker está correto e qualquer problema restante está na sua aplicação.

Para uma verificação automatizada, este script com MQTT.js 5 roda no Node.js ou, quase sem mudanças, no navegador:

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, // falhar rápido durante o teste
});

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"));

O MQTT.js define o subprotocolo mqtt automaticamente. Python também funciona — paho-mqtt 2.x com 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()  # remova para ws:// na porta 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()

O caminho WebSocket padrão do paho já é /mqtt, então ws_set_options é opcional aqui — mas brokers que usam / ou um caminho próprio respondem com 404 até você defini-lo explicitamente.

Depurando no DevTools do navegador

Quando uma aplicação web não consegue conectar, o navegador mostra todos os detalhes do handshake:

  1. Abra o DevTools → Network, filtre por WS (Chrome) ou escolha WS no filtro de tipo (Firefox) e recarregue a página.
  2. Clique na requisição do socket. Em Headers, confira o status (101), a URL e o caminho, e se tanto a requisição quanto a resposta incluem Sec-WebSocket-Protocol: mqtt.
  3. Abra a aba Messages (Chrome) ou Response (Firefox). O primeiro frame enviado é o CONNECT MQTT binário; o primeiro recebido é o CONNACK. Se o CONNECT sai e o socket fecha sem CONNACK, o broker rejeitou a sessão MQTT (credenciais, client ID), e não o WebSocket.
  4. Procure no Console erros como estes:
Erros típicos no console
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.

O primeiro, sem nada depois dos dois-pontos, é a falha genérica do navegador — geralmente porta, caminho ou certificado errados; confira a aba Network. O segundo só se resolve trocando para wss:// (conteúdo misto). Um código de fechamento 1006 significa que a conexão caiu sem um frame de fechamento adequado, muitas vezes por timeout do proxy ou porque o broker recusou a conexão. Para a lista completa de causas, veja MQTT WebSocket connection failed.

Checklist de testes WebSocket

  1. O curl na URL wss:// retorna 101 e devolve Sec-WebSocket-Protocol: mqtt.
  2. O wscat com -s mqtt conecta; sem ele, o broker recusa ou fecha.
  3. Um cliente real recebe um CONNACK e completa um ciclo de publish/subscribe.
  4. O navegador conecta a partir de uma página HTTPS com wss://, sem erros no console.
  5. Através do seu proxy ou load balancer, conexões ociosas sobrevivem por mais tempo que o intervalo de keep-alive.
  6. Credenciais e ACLs se comportam da mesma forma no listener WebSocket e no TCP.

Teste o endpoint WebSocket no seu navegador

Problemas de WebSocket só parecem misteriosos até você dividi-los em dois. Prove o upgrade HTTP com curl ou wscat, depois a sessão MQTT com um cliente real, e em minutos você saberá se precisa corrigir a URL, o proxy ou as credenciais MQTT.

Perguntas frequentes

Qual é o caminho WebSocket do MQTT?

Não existe um padrão único. /mqtt é o mais comum (EMQX, HiveMQ e ConnectMQ usam, e proxies na frente do Mosquitto costumam roteá-lo), mas alguns brokers escutam em / ou num caminho próprio. Um caminho errado normalmente retorna HTTP 404 durante o handshake.

Qual subprotocolo WebSocket o MQTT usa?

mqtt, tanto no MQTT 3.1.1 quanto no MQTT 5. Clientes antigos de MQTT 3.1 usavam mqttv3.1. O cliente envia o valor em Sec-WebSocket-Protocol e o broker precisa devolvê-lo na resposta 101; se não devolver, os navegadores derrubam a conexão.

O mosquitto_pub consegue conectar via WebSockets?

Não. Os clientes de linha de comando do mosquitto só falam MQTT sobre TCP e TLS. Para testar um listener WebSocket, use um cliente no navegador, MQTT.js, paho-mqtt com transport="websockets" ou um cliente desktop como o MQTTX.