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