Pluggable transport layer supporting WebSocket, polling, and WebTransport protocols with automatic fallback mechanisms and upgrade capabilities for reliable cross-platform connectivity.
Comprehensive configuration interface for controlling transport behavior, connection parameters, and protocol options.
/**
* Configuration options for Socket instances
* Controls transport selection, connection parameters, and protocol behavior
*/
interface SocketOptions {
// Connection parameters
host?: string;
hostname?: string;
secure?: boolean;
port?: string | number;
query?: { [key: string]: any };
// Transport configuration
transports?: ("polling" | "websocket" | "webtransport" | string)[] | TransportCtor[];
upgrade?: boolean;
tryAllTransports?: boolean;
rememberUpgrade?: boolean;
// Protocol options
forceBase64?: boolean;
timestampParam?: string;
timestampRequests?: boolean;
requestTimeout?: number;
path?: string;
addTrailingSlash?: boolean;
protocols?: string | string[];
// Node.js specific options
agent?: string | boolean;
transportOptions?: Object;
// SSL/TLS options
pfx?: string;
key?: string;
passphrase?: string;
cert?: string;
ca?: string | string[];
ciphers?: string;
rejectUnauthorized?: boolean;
// HTTP options
extraHeaders?: { [header: string]: string };
withCredentials?: boolean;
// Behavior options
closeOnBeforeunload?: boolean;
useNativeTimers?: boolean;
autoUnref?: boolean;
perMessageDeflate?: { threshold: number };
}Usage Examples:
import { Socket } from "engine.io-client";
// Basic configuration
const socket = new Socket("ws://localhost:3000", {
transports: ["websocket", "polling"],
upgrade: true,
query: { userId: "123" }
});
// Advanced configuration
const socket = new Socket({
hostname: "api.example.com",
secure: true,
port: 443,
path: "/realtime/",
transports: ["polling", "websocket", "webtransport"],
tryAllTransports: true,
rememberUpgrade: true,
extraHeaders: {
"Authorization": "Bearer token123"
},
transportOptions: {
polling: {
extraHeaders: {
"X-Custom-Header": "value"
}
}
}
});
// Node.js specific configuration
const socket = new Socket("https://secure.example.com", {
key: fs.readFileSync("client.key"),
cert: fs.readFileSync("client.crt"),
ca: fs.readFileSync("ca.crt"),
rejectUnauthorized: true
});Abstract base class for all transport implementations providing common interface and event handling.
/**
* Abstract base class for all transport implementations
* Provides common interface and event handling capabilities
*/
abstract class Transport extends Emitter<
Record<never, never>,
Record<never, never>,
TransportReservedEvents
> {
// Public properties
query: Record<string, string>;
writable: boolean;
// Abstract properties
abstract get name(): string;
// Public methods
open(): Transport;
close(): Transport;
send(packets: Packet[]): void;
pause(onPause: () => void): void;
// Abstract methods (must be implemented by subclasses)
protected abstract doOpen(): void;
protected abstract doClose(): void;
protected abstract write(packets: Packet[]): void;
// Protected methods (for subclass use)
protected onError(reason: string, description: any, context?: any): Transport;
protected onOpen(): void;
protected onData(data: RawData): void;
protected onPacket(packet: Packet): void;
protected onClose(details?: CloseDetails): void;
// Protected properties (for implementation)
protected opts: SocketOptions;
protected supportsBinary: boolean;
protected readyState: TransportState;
protected socket: Socket;
protected setTimeoutFn: typeof setTimeout;
}
type TransportState = "opening" | "open" | "closed" | "pausing" | "paused";
interface TransportReservedEvents {
open: () => void;
error: (err: TransportError) => void;
packet: (packet: Packet) => void;
close: (details?: CloseDetails) => void;
poll: () => void;
pollComplete: () => void;
drain: () => void;
}Specialized error class for transport-specific errors with context information.
/**
* Transport-specific error class with context information
* Provides detailed error information for debugging transport issues
*/
class TransportError extends Error {
readonly type: "TransportError";
readonly description: any;
readonly context: any;
constructor(reason: string, description: any, context: any);
}
interface CloseDetails {
description: string;
context?: unknown;
}Usage Examples:
socket.on("error", (error) => {
if (error instanceof TransportError) {
console.error("Transport error:", error.description);
console.error("Context:", error.context);
}
});Built-in transport implementations for different environments and protocols.
/**
* Available transport constructors
* Platform-specific implementations are automatically selected
*/
const transports: {
websocket: typeof WS;
webtransport: typeof WT;
polling: typeof XHR;
};
// Individual transport classes
class XHR extends BaseXHR {
// XMLHttpRequest-based polling transport for browsers
}
class NodeXHR extends BaseXHR {
// HTTP-based polling transport for Node.js
}
class Fetch extends Polling {
// Fetch API-based polling transport
}
class WebSocket extends BaseWS {
// Browser WebSocket transport
}
class NodeWebSocket extends BaseWS {
// Node.js WebSocket transport
}
class WebTransport extends Transport {
// WebTransport-based transport
}Usage Examples:
import { Socket, transports } from "engine.io-client";
// Use all available transports
const socket = new Socket("ws://localhost:3000");
// Use specific transports only
const socket = new Socket("ws://localhost:3000", {
transports: ["websocket"]
});
// Tree-shaking with specific transport imports
import { SocketWithoutUpgrade, WebSocket } from "engine.io-client";
const socket = new SocketWithoutUpgrade({
hostname: "localhost",
port: 3000,
transports: [WebSocket]
});Detailed configuration options for each transport type and protocol behavior.
interface TransportSpecificOptions {
// Polling transport options
requestTimeout?: number;
// WebSocket options
protocols?: string | string[];
perMessageDeflate?: { threshold: number };
// General transport options
transportOptions?: {
polling?: {
extraHeaders?: { [header: string]: string };
};
websocket?: {
extraHeaders?: { [header: string]: string };
};
webtransport?: {
[key: string]: any;
};
};
}Usage Examples:
// Configure polling timeout
const socket = new Socket("http://localhost:3000", {
transports: ["polling"],
requestTimeout: 10000
});
// Configure WebSocket subprotocols
const socket = new Socket("ws://localhost:3000", {
transports: ["websocket"],
protocols: ["echo-protocol", "chat"]
});
// Configure per-message deflate
const socket = new Socket("ws://localhost:3000", {
perMessageDeflate: {
threshold: 1024
}
});
// Transport-specific headers
const socket = new Socket("http://localhost:3000", {
transportOptions: {
polling: {
extraHeaders: {
"X-Polling-Token": "abc123"
}
},
websocket: {
extraHeaders: {
"X-WebSocket-Token": "def456"
}
}
}
});Automatic transport upgrading for improved performance and reliability.
interface UpgradeOptions {
upgrade?: boolean;
tryAllTransports?: boolean;
rememberUpgrade?: boolean;
}Usage Examples:
// Enable automatic upgrading (default behavior)
const socket = new Socket("http://localhost:3000", {
upgrade: true,
transports: ["polling", "websocket"]
});
// Test all transports on connection failure
const socket = new Socket("http://localhost:3000", {
tryAllTransports: true
});
// Remember successful WebSocket upgrades
const socket = new Socket("http://localhost:3000", {
rememberUpgrade: true
});
// Listen for upgrade events
socket.on("upgrading", (transport) => {
console.log("Upgrading to:", transport.name);
});
socket.on("upgrade", (transport) => {
console.log("Upgraded to:", transport.name);
});
socket.on("upgradeError", (error) => {
console.error("Upgrade failed:", error);
});type TransportName = "polling" | "websocket" | "webtransport";
type TransportState = "opening" | "open" | "closed" | "pausing" | "paused";
type TransportCtor = { new (o: any): Transport };
interface BaseSocketOptions extends Omit<SocketOptions, "transports"> {
transports: TransportCtor[];
}
interface Packet {
type: PacketType;
data?: RawData;
}
type PacketType = "open" | "close" | "ping" | "pong" | "message" | "upgrade" | "noop";