The realtime engine behind Socket.IO providing bidirectional connection foundation between client and server
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pluggable transport layer with automatic fallback and upgrade capabilities supporting polling, WebSocket, and WebTransport protocols.
Abstract base class for all transport implementations.
/**
* Base class for all transport implementations
*/
abstract class Transport extends EventEmitter {
/** Transport name identifier */
abstract readonly name: string;
/** Session ID for this transport */
readonly sid: string;
/** Protocol version */
readonly protocol: number;
/** Whether transport can send data */
writable: boolean;
/** Current transport state */
readyState: ReadyState;
/**
* Create transport instance (internal use)
* @param req - HTTP request object
*/
constructor(req: IncomingMessage);
/**
* Send packets through this transport
* @param packets - Array of packets to send
*/
abstract send(packets: Packet[]): void;
/**
* Handle incoming request for this transport
* @param req - HTTP request
*/
onRequest(req: IncomingMessage): void;
/**
* Close transport connection
* @param fn - Optional callback
*/
close(fn?: () => void): void;
/**
* Mark transport as discarded
*/
discard(): void;
/**
* Implementation-specific close method
* @param fn - Optional callback
*/
protected abstract doClose(fn?: () => void): void;
}HTTP long-polling transport for fallback compatibility and cross-domain support.
/**
* HTTP long-polling transport
*/
class Polling extends Transport {
readonly name: "polling";
/** Maximum HTTP buffer size */
maxHttpBufferSize: number;
/** HTTP compression settings */
httpCompression: any;
/** Whether compression is supported */
supportsCompression: boolean;
/**
* Send packets via HTTP response
*/
send(packets: Packet[]): void;
/**
* Handle polling request
*/
onPollRequest(req: IncomingMessage, res: ServerResponse): void;
/**
* Handle data submission request
*/
onDataRequest(req: IncomingMessage, res: ServerResponse): void;
}JSONP polling transport for cross-domain support in legacy browsers.
/**
* JSONP polling transport extending Polling
*/
class JSONP extends Polling {
readonly name: "polling";
/** JSONP callback parameter name */
jsonp: string;
/**
* Override to send JSONP-wrapped responses
*/
send(packets: Packet[]): void;
}WebSocket transport for real-time bidirectional communication.
/**
* WebSocket transport for real-time communication
*/
class WebSocket extends Transport {
readonly name: "websocket";
/** Handles transport upgrades */
readonly handlesUpgrades: true;
/** WebSocket permessage-deflate settings */
perMessageDeflate: any;
/** WebSocket instance */
socket: any;
/**
* Send packets through WebSocket
*/
send(packets: Packet[]): void;
/**
* Handle WebSocket connection
*/
onWebSocket(socket: any): void;
}Modern WebTransport implementation for HTTP/3 connections.
/**
* WebTransport implementation for HTTP/3
*/
class WebTransport extends Transport {
readonly name: "webtransport";
/** WebTransport session */
session: any;
/** Readable stream */
readable: ReadableStream;
/** Writable stream */
writable: WritableStream;
/**
* Send packets through WebTransport
*/
send(packets: Packet[]): void;
/**
* Handle WebTransport session
*/
onSession(session: any): void;
}/**
* Registry of available transport implementations
*/
interface TransportRegistry {
/** Polling transport factory (returns XHR or JSONP based on request) */
polling: (req: IncomingMessage) => Polling | JSONP;
/** WebSocket transport class */
websocket: typeof WebSocket;
/** WebTransport class */
webtransport: typeof WebTransport;
}
/**
* Available transport registry
*/
const transports: TransportRegistry;Engine.IO uses a priority system for transport selection:
// Configure transport priority
const server = new Server({
transports: ['polling', 'websocket', 'webtransport']
});server.on('connection', (socket) => {
console.log('Initial transport:', socket.transport.name);
socket.on('upgrade', (transport) => {
console.log('Upgraded to:', transport.name);
});
socket.on('upgrading', (transport) => {
console.log('Upgrading to:', transport.name);
});
});const server = new Server({
// HTTP compression for polling
httpCompression: {
threshold: 1024,
level: 6,
memLevel: 8
},
// Maximum buffer size for HTTP requests
maxHttpBufferSize: 1e6, // 1MB
// CORS settings for polling
cors: {
origin: true,
credentials: true
}
});const server = new Server({
// Custom WebSocket engine (e.g., eiows for better performance)
wsEngine: require('eiows').Server,
// WebSocket compression
perMessageDeflate: {
threshold: 1024,
concurrencyLimit: 10,
deflateOptions: {
chunkSize: 1024,
windowBits: 13,
memLevel: 7
}
}
});const server = new Server({
// Enable WebTransport (disabled by default)
transports: ['polling', 'websocket', 'webtransport'],
// WebTransport-specific options would go here
// (implementation-specific)
});interface TransportEvents {
/** Emitted when transport is ready */
open: () => void;
/** Emitted when transport is closed */
close: () => void;
/** Emitted when packet is received */
packet: (packet: Packet) => void;
/** Emitted when data is received */
data: (data: string | Buffer) => void;
/** Emitted on transport error */
error: (error: Error) => void;
/** Emitted when transport is discarded */
drain: () => void;
}// Example custom transport
class CustomTransport extends Transport {
readonly name = "custom";
constructor(req: IncomingMessage) {
super(req);
// Custom initialization
}
send(packets: Packet[]): void {
// Implement packet sending
packets.forEach(packet => {
this.sendPacket(packet);
});
}
protected doClose(fn?: () => void): void {
// Implement transport-specific cleanup
this.cleanup();
fn?.();
}
private sendPacket(packet: Packet): void {
// Custom packet sending logic
}
private cleanup(): void {
// Custom cleanup logic
}
}
// Register custom transport
server.transports.custom = CustomTransport;// Optimize polling for your use case
const server = new Server({
// Reduce HTTP overhead
maxHttpBufferSize: 100 * 1024, // 100KB
// Enable compression for large payloads
httpCompression: {
threshold: 512 // Compress messages > 512 bytes
},
// Faster heartbeat for quicker connection detection
pingInterval: 10000, // 10 seconds
pingTimeout: 5000 // 5 seconds
});// Optimize WebSocket performance
const server = new Server({
// Use high-performance WebSocket engine
wsEngine: require('eiows').Server,
// Optimize compression
perMessageDeflate: {
threshold: 1024,
deflateOptions: {
level: 1, // Fast compression
windowBits: 13
}
}
});// Enable transport debugging
process.env.DEBUG = 'engine:transport:*';
server.on('connection', (socket) => {
// Log transport changes
socket.on('upgrading', (transport) => {
console.log(`${socket.id}: Upgrading from ${socket.transport.name} to ${transport.name}`);
});
socket.on('upgrade', (transport) => {
console.log(`${socket.id}: Successfully upgraded to ${transport.name}`);
});
// Monitor transport errors
socket.transport.on('error', (error) => {
console.error(`Transport error for ${socket.id}:`, error);
});
});