Mudar de JSON para MsgPack de forma retrocompatível com Paho MQTT (JavaScript)
picockpit.com faz uso pesado do MQTT. Para a próxima versão 2.0 eu decidi mudá-la para MsgPack.
Porquê MsgPack?
MsgPack (na verdade chamado MessagePack - pacotes tendem a usar o MsgPack) é um formato binário, visando a compatibilidade com o JSON, mas diminuindo o tamanho do arquivo (o que é bom para economizar largura de banda & recursos do servidor).
Outra vantagem: MessagePack permite a incorporação de dados binários (há alguns casos de uso emocionantes planejados para PiCockpit v2.1+).
Em comparação com outros formatos de serialização binária (por exemplo, BSON) o MsgPack visa uma maior compatibilidade com o JSON, é mais compacto, e pode ser descodificado como um fluxo!
Mensagens retidas do passado
Devido às mensagens retidas ainda estarem no JSON (e também clientes antigos que ainda enviam mensagens JSON), no entanto, a compatibilidade retroativa precisa ser fornecida, especialmente no lado JavaScript.
A falta de compatibilidade retroativa levará aos seguintes problemas com o Paho:
onConnectFailure;A conexão MQTT falhou (5): AMQJS0005E Erro interno. Mensagem de erro: AMQJS0009E dados malformados UTF:ad -4f ., Stack trace: Sem pilha de erro disponível
onConnectFailure;A conexão MQTT falhou (5): AMQJS0005E Erro interno. Mensagem de erro: Extra 231 byte(s) encontrado(s) no buffer[1], Stack trace: Sem pilha de erro disponível
Codificação de retorno para o JSON
Paho não nos dá acesso aos dados da mensagem em si (ver Código Paho aqui).
Portanto, podemos voltar à captura de exceções, assumindo que a mensagem provavelmente estará no formato MsgPack, e se a decodificação falhar, mudará para o JSON.
E se a descodificação do JSON falhar, nós damos uma resposta contra o fuzzing:
extractMessage(mensagem){
// 20.7.2020: mudar para msgPack; tem de ser payloadBytes, não payloadString
var descodificadoMensagem = {};
tente {
decodedMessage = decode(message.payloadBytes);
}
catch (e){
console.log("erro de decodificação detectado");
console.log(e);
tente {
decodedMessage = JSON.parse(message.payloadString);
}
catch (e){
console.log("mensagem mal-formada (nem JSON nem MsgPack) - interpretando como objeto vazio {}");
}
}
devolverMensagem descodificada;
// devolver JSON.parse(message.payloadString);
}
- note que usamos payloadBytes para acessar a mensagem para msgPack, e payloadString para a decodificação do JSON
- Note que a descodificação (e codificação) está incluída assim: importar { codificar, descodificar } de "@msgpack/msgpack"; no meu Webpack Workflow
Referências
- MessagePack (msgpack.org)
- msgpack JavaScript library (use este em vez do que está ligado no msgpack.org, pois tem actividade mais recente)
- Paho MQTT JS Código Fonte
- Paho MQTT Documentação JS para a Mensagem da Turma