Parser personalizado
Desde Socket.IO v2.0.0, ahora es posible proporcionar tu propio parser, para controlar el marshalling / unmarshalling de paquetes.
Servidor
import{Server}from"socket.io";
const io =newServer({
parser: myParser
});
Cliente
import{ io }from"socket.io-client";
const socket =io({
parser: myParser
});
Parsers disponibles
Además del parser por defecto, aquí está la lista de parsers disponibles:
| Paquete | Descripción |
|---|---|
socket.io-circular-parser | Similar al parser por defecto, pero maneja referencias circulares. |
socket.io-msgpack-parser | Usa MessagePack para codificar los paquetes (basado en el paquete notepack.io). |
@skgdev/socket.io-msgpack-javascript | Usa MessagePack para codificar los paquetes (basado en el paquete @msgpack/msgpack). |
socket.io-json-parser | Usa JSON.stringify() y JSON.parse() para codificar los paquetes. |
socket.io-cbor-x-parser | Usa cbor-x para codificar los paquetes. |
@socket.io/devalue-parser | Usa devalue para codificar los paquetes. |
Implementando tu propio parser
Aquí hay un ejemplo básico con un parser que usa los métodos JSON.stringify() y JSON.parse():
import{Emitter}from"@socket.io/component-emitter";// polyfill de Node.js EventEmitter en el navegador
classEncoder{
/**
* Codificar un paquete en una lista de strings/buffers
*/
encode(packet){
return[JSON.stringify(packet)];
}
}
functionisObject(value){
returnObject.prototype.toString.call(value)==="[object Object]";
}
classDecoderextendsEmitter{
/**
* Recibir un fragmento (string o buffer) y opcionalmente emitir un evento "decoded" con el paquete reconstruido
*/
add(chunk){
const packet =JSON.parse(chunk);
if(this.isPacketValid(packet)){
this.emit("decoded", packet);
}else{
thrownewError("formato inválido");
}
}
isPacketValid({ type, data, nsp, id }){
const isNamespaceValid =typeof nsp ==="string";
const isAckIdValid = id ===undefined||Number.isInteger(id);
if(!isNamespaceValid ||!isAckIdValid){
returnfalse;
}
switch(type){
case0:// CONNECT
return data ===undefined||isObject(data);
case1:// DISCONNECT
return data ===undefined;
case2:// EVENT
returnArray.isArray(data)&&typeof data[0]==="string";
case3:// ACK
returnArray.isArray(data);
case4:// CONNECT_ERROR
returnisObject(data);
default:
returnfalse;
}
}
/**
* Limpiar buffers internos
*/
destroy(){}
}
exportconst parser ={Encoder,Decoder};
El parser por defecto
El código fuente del parser por defecto (el paquete socket.io-parser) se puede encontrar aquí: https://github.com/socketio/socket.io-parser
Ejemplo de salida:
- emit básico
socket.emit("test",42);
será codificado como:
2["test",42]
|||
||└─ carga útil codificada en JSON
|└─ tipo de paquete (2 => EVENT)
- emit con binario, acknowledgement y namespace personalizado
socket.emit("test",Uint8Array.from([42]),()=>{
console.log("ack recibido");
});
será codificado como:
51-/admin,13["test",{"_placeholder":true,"num":0}]
||||| || └─ carga útil codificada en JSON con placeholders para adjuntos binarios
||||| |└─ id de acknowledgement
||||| └─ separador
||||└─ namespace (no incluido cuando es el namespace principal)
|||└─ separador
||└─ número de adjuntos binarios
|└─ tipo de paquete (5 => BINARY EVENT)
y un adjunto adicional (el Uint8Array extraído)
Pros:
- el adjunto binario se codifica en base64, así que este parser es compatible con navegadores que no soportan Arraybuffers, como IE9
Contras:
- los paquetes con contenido binario se envían como dos frames WebSocket distintos (si la conexión WebSocket está establecida)
El parser msgpack
Este parser usa el formato de serialización MessagePack.
El código fuente de este parser se puede encontrar aquí: https://github.com/socketio/socket.io-msgpack-parser
Uso de ejemplo:
Servidor
import{Server}from"socket.io";
importcustomParserfrom"socket.io-msgpack-parser";
const io =newServer({
parser: customParser
});
Cliente (Node.js)
import{ io }from"socket.io-client";
importcustomParserfrom"socket.io-msgpack-parser";
const socket =io("https://example.com",{
parser: customParser
});
En el navegador, ahora hay un bundle oficial que incluye este parser:
- https://cdn.socket.io/4.8.1/socket.io.msgpack.min.js
- cdnjs: https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.8.1/socket.io.msgpack.min.js
- jsDelivr: https://cdn.jsdelivr.net/npm/socket.io-client@4.8.1/dist/socket.io.msgpack.min.js
- unpkg: https://unpkg.com/socket.io-client@4.8.1/dist/socket.io.msgpack.min.js
En ese caso, no necesitas especificar la opción parser.
Pros:
- los paquetes con contenido binario se envían como un solo frame WebSocket (si la conexión WebSocket está establecida)
- puede resultar en cargas útiles más pequeñas (especialmente cuando se usan muchos números)
Contras:
- incompatible con navegadores que no soportan Arraybuffers, como IE9
- más difícil de depurar en la pestaña Network del navegador
Por favor ten en cuenta que socket.io-msgpack-parser se basa en la implementación de MessagePack notepack.io. Esta implementación se enfoca principalmente en el rendimiento y el tamaño mínimo del bundle, y por lo tanto no soporta características como tipos de extensión. Para un parser basado en la implementación oficial de JavaScript, por favor revisa este paquete.