Skip to content

improvements to internal types #5364

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/engine.io-parser/lib/commons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export type RawData = any;

export interface Packet {
type: PacketType;
options?: { compress: boolean };
options?: { compress: boolean, wsPreEncoded?: string, wsPreEncodedFrame?: boolean };
data?: RawData;
}

Expand Down
30 changes: 17 additions & 13 deletions packages/engine.io/lib/engine.io.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createServer } from "http";
import { createServer, Server as HttpServer } from "http";
import { Server, AttachOptions, ServerOptions } from "./server";
import transports from "./transports/index";
import * as parser from "engine.io-parser";
Expand All @@ -11,17 +11,21 @@ export { Transport } from "./transport";
export const protocol = parser.protocol;

/**
* Creates an http.Server exclusively used for WS upgrades.
* Creates an http.Server exclusively used for WS upgrades, and start listening.
*
* @param {Number} port
* @param {Function} callback
* @param {Object} options
* @return {Server} websocket.io server
* @param port
* @param options
* @param listenCallback callback for http.Server.listen()
* @return engine.io server
*/

function listen(port, options: AttachOptions & ServerOptions, fn) {
function listen(
port: number,
options?: AttachOptions & ServerOptions,
listenCallback?: () => void,
): Server {
if ("function" === typeof options) {
fn = options;
listenCallback = options;
options = {};
}

Expand All @@ -34,20 +38,20 @@ function listen(port, options: AttachOptions & ServerOptions, fn) {
const engine = attach(server, options);
engine.httpServer = server;

server.listen(port, fn);
server.listen(port, listenCallback);

return engine;
}

/**
* Captures upgrade requests for a http.Server.
*
* @param {http.Server} server
* @param {Object} options
* @return {Server} engine server
* @param server
* @param options
* @return engine.io server
*/

function attach(server, options: AttachOptions & ServerOptions) {
function attach(server: HttpServer, options: AttachOptions & ServerOptions): Server {
const engine = new Server(options);
engine.attach(server, options);
return engine;
Expand Down
14 changes: 7 additions & 7 deletions packages/engine.io/lib/parser-v3/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ const EMPTY_BUFFER = Buffer.concat([]);
*
* @api private
*/

export function encodePacket (packet, supportsBinary, utf8encode, callback) {
export function encodePacket (packet: any, supportsBinary?: any, utf8encode?: any, callback?: any) {
if (typeof supportsBinary === 'function') {
callback = supportsBinary;
supportsBinary = null;
Expand All @@ -86,7 +85,7 @@ export function encodePacket (packet, supportsBinary, utf8encode, callback) {
}

return callback('' + encoded);
};
}

/**
* Encode Buffer data
Expand Down Expand Up @@ -120,16 +119,16 @@ export function encodeBase64Packet (packet, callback){
/**
* Decodes a packet. Data also available as an ArrayBuffer if requested.
*
* @return {Object} with `type` and `data` (if any)
* @return {import('engine.io-parser').Packet} with `type` and `data` (if any)
* @api private
*/

export function decodePacket (data, binaryType, utf8decode) {
export function decodePacket (data: any, binaryType?: any, utf8decode?: any): any {
if (data === undefined) {
return err;
}

var type;
let type: string | number;

// String data
if (typeof data === 'string') {
Expand All @@ -147,6 +146,7 @@ export function decodePacket (data, binaryType, utf8decode) {
}
}

// @ts-expect-error
if (Number(type) != type || !packetslist[type]) {
return err;
}
Expand Down Expand Up @@ -274,7 +274,7 @@ function map(ary, each, done) {
* @api public
*/

export function decodePayload (data, binaryType, callback) {
export function decodePayload (data: any, binaryType?: any, callback?: any) {
if (typeof data !== 'string') {
return decodePayloadAsBinary(data, binaryType, callback);
}
Expand Down
83 changes: 53 additions & 30 deletions packages/engine.io/lib/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import { EventEmitter } from "events";
import { Socket } from "./socket";
import debugModule from "debug";
import { serialize } from "cookie";
import { Server as DEFAULT_WS_ENGINE } from "ws";
import {
Server as DEFAULT_WS_ENGINE,
type Server as WsServer,
type PerMessageDeflateOptions,
type WebSocket as WsWebSocket,
} from "ws";
import type {
IncomingMessage,
Server as HttpServer,
Expand All @@ -16,7 +21,7 @@ import type { CorsOptions, CorsOptionsDelegate } from "cors";
import type { Duplex } from "stream";
import { WebTransport } from "./transports/webtransport";
import { createPacketDecoderStream } from "engine.io-parser";
import type { EngineRequest } from "./transport";
import type { EngineRequest, Transport as TransportImpl } from "./transport";
import type { CookieSerializeOptions } from "./contrib/types.cookie";

const debug = debugModule("engine");
Expand All @@ -25,6 +30,11 @@ const kResponseHeaders = Symbol("responseHeaders");

type Transport = "polling" | "websocket" | "webtransport";

export type ErrorCallback = (
errorCode?: (typeof Server.errors)[keyof typeof Server.errors],
errorContext?: Record<string, unknown> & { name?: string; message?: string },
) => void;

export interface AttachOptions {
/**
* name of the path to capture
Expand Down Expand Up @@ -100,7 +110,7 @@ export interface ServerOptions {
* parameters of the WebSocket permessage-deflate extension (see ws module api docs). Set to false to disable.
* @default false
*/
perMessageDeflate?: boolean | object;
perMessageDeflate?: boolean | PerMessageDeflateOptions;
/**
* parameters of the http compression for the polling transports (see zlib api docs). Set to false to disable.
* @default true
Expand All @@ -113,7 +123,7 @@ export interface ServerOptions {
*
* @default `require("ws").Server`
*/
wsEngine?: any;
wsEngine?: typeof WsServer;
/**
* an optional packet which will be concatenated to the handshake packet emitted by Engine.IO.
*/
Expand Down Expand Up @@ -149,7 +159,7 @@ type Middleware = (
next: (err?: any) => void,
) => void;

function parseSessionId(data: string) {
function parseSessionId(data: string): string | undefined {
try {
const parsed = JSON.parse(data);
if (typeof parsed.sid === "string") {
Expand Down Expand Up @@ -224,7 +234,7 @@ export abstract class BaseServer extends EventEmitter {
this.init();
}

protected abstract init();
protected abstract init(): void;

/**
* Compute the pathname of the requests that are handled by the server
Expand All @@ -244,10 +254,8 @@ export abstract class BaseServer extends EventEmitter {

/**
* Returns a list of available transports for upgrade given a certain transport.
*
* @return {Array}
*/
public upgrades(transport: string) {
public upgrades(transport: Transport): string[] {
if (!this.opts.allowUpgrades) return [];
return transports[transport].upgradesTo || [];
}
Expand All @@ -259,17 +267,18 @@ export abstract class BaseServer extends EventEmitter {
* @param upgrade - whether it's an upgrade request
* @param fn
* @protected
* @return whether the request is valid
*/
protected verify(
req: any,
req: EngineRequest,
upgrade: boolean,
fn: (errorCode?: number, errorContext?: any) => void,
) {
fn: ErrorCallback,
): void | boolean {
// transport check
const transport = req._query.transport;
// WebTransport does not go through the verify() method, see the onWebTransportSession() method
if (
!~this.opts.transports.indexOf(transport) ||
!~this.opts.transports.indexOf(transport as Transport) ||
transport === "webtransport"
) {
debug('unknown transport "%s"', transport);
Expand Down Expand Up @@ -408,7 +417,7 @@ export abstract class BaseServer extends EventEmitter {
*
* @param {IncomingMessage} req - the request object
*/
public generateId(req: IncomingMessage) {
public generateId(req: IncomingMessage): string | PromiseLike<string> {
return base64id.generateId();
}

Expand All @@ -423,8 +432,8 @@ export abstract class BaseServer extends EventEmitter {
*/
protected async handshake(
transportName: string,
req: any,
closeConnection: (errorCode?: number, errorContext?: any) => void,
req: EngineRequest,
closeConnection: ErrorCallback,
) {
const protocol = req._query.EIO === "4" ? 4 : 3; // 3rd revision by default
if (protocol === 3 && !this.opts.allowEIO3) {
Expand Down Expand Up @@ -600,7 +609,7 @@ export abstract class BaseServer extends EventEmitter {
}
}

protected abstract createTransport(transportName, req);
protected abstract createTransport(transportName: Transport, req: EngineRequest);

/**
* Protocol errors mappings.
Expand All @@ -613,7 +622,7 @@ export abstract class BaseServer extends EventEmitter {
BAD_REQUEST: 3,
FORBIDDEN: 4,
UNSUPPORTED_PROTOCOL_VERSION: 5,
};
} as const;

static errorMessages = {
0: "Transport unknown",
Expand All @@ -622,7 +631,7 @@ export abstract class BaseServer extends EventEmitter {
3: "Bad request",
4: "Forbidden",
5: "Unsupported protocol version",
};
} as const;
}

/**
Expand Down Expand Up @@ -667,7 +676,7 @@ class WebSocketResponse {
*/
export class Server extends BaseServer {
public httpServer?: HttpServer;
private ws: any;
private ws: WsServer;

/**
* Initialize websocket server
Expand All @@ -687,7 +696,7 @@ export class Server extends BaseServer {
});

if (typeof this.ws.on === "function") {
this.ws.on("headers", (headersArray, req) => {
this.ws.on("headers", (headersArray, req: EngineRequest) => {
// note: 'ws' uses an array of headers, while Engine.IO uses an object (response.writeHead() accepts both formats)
// we could also try to parse the array and then sync the values, but that will be error-prone
const additionalHeaders = req[kResponseHeaders] || {};
Expand Down Expand Up @@ -730,7 +739,8 @@ export class Server extends BaseServer {
}
}

protected createTransport(transportName: string, req: IncomingMessage) {
protected createTransport(transportName: Transport, req: IncomingMessage) {
// @ts-expect-error 'polling' is a plain function used as constructor
return new transports[transportName](req);
}

Expand All @@ -745,7 +755,7 @@ export class Server extends BaseServer {
this.prepare(req);
req.res = res;

const callback = (errorCode, errorContext) => {
const callback: ErrorCallback = (errorCode, errorContext) => {
if (errorCode !== undefined) {
this.emit("connection_error", {
req,
Expand Down Expand Up @@ -787,7 +797,7 @@ export class Server extends BaseServer {
this.prepare(req);

const res = new WebSocketResponse(req, socket);
const callback = (errorCode, errorContext) => {
const callback: ErrorCallback = (errorCode, errorContext) => {
if (errorCode !== undefined) {
this.emit("connection_error", {
req,
Expand Down Expand Up @@ -823,11 +833,16 @@ export class Server extends BaseServer {

/**
* Called upon a ws.io connection.
*
* @param {ws.Socket} websocket
* @param req
* @param socket
* @param websocket
* @private
*/
private onWebSocket(req, socket, websocket) {
private onWebSocket(
req: EngineRequest,
socket: Duplex,
websocket: WsWebSocket,
) {
websocket.on("error", onUpgradeError);

if (
Expand Down Expand Up @@ -862,7 +877,11 @@ export class Server extends BaseServer {
// transport error handling takes over
websocket.removeListener("error", onUpgradeError);

const transport = this.createTransport(req._query.transport, req);
const transport: TransportImpl = this.createTransport(
req._query.transport,
req
);
// @ts-expect-error this option is only for WebSocket impl
transport.perMessageDeflate = this.opts.perMessageDeflate;
client._maybeUpgrade(transport);
}
Expand Down Expand Up @@ -947,7 +966,11 @@ export class Server extends BaseServer {
* @private
*/

function abortRequest(res, errorCode, errorContext) {
function abortRequest(
res: ServerResponse,
errorCode: number,
errorContext?: { message?: string },
) {
const statusCode = errorCode === Server.errors.FORBIDDEN ? 403 : 400;
const message =
errorContext && errorContext.message
Expand Down Expand Up @@ -1030,7 +1053,7 @@ const validHdrChars = [
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // ... 255
]

function checkInvalidHeaderChar(val) {
function checkInvalidHeaderChar(val?: string) {
val += "";
if (val.length < 1) return false;
if (!validHdrChars[val.charCodeAt(0)]) {
Expand Down
5 changes: 3 additions & 2 deletions packages/engine.io/lib/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { EngineRequest, Transport } from "./transport";
import type { BaseServer } from "./server";
import { setTimeout, clearTimeout } from "timers";
import type { Packet, PacketType, RawData } from "engine.io-parser";
import type transports from "./transports";

const debug = debugModule("engine:socket");

Expand Down Expand Up @@ -537,9 +538,9 @@ export class Socket extends EventEmitter {
*/
private getAvailableUpgrades() {
const availableUpgrades = [];
const allUpgrades = this.server.upgrades(this.transport.name);
const allUpgrades = this.server.upgrades(this.transport.name as keyof typeof transports);
for (let i = 0; i < allUpgrades.length; ++i) {
const upg = allUpgrades[i];
const upg = allUpgrades[i] as keyof typeof transports;
if (this.server.opts.transports.indexOf(upg) !== -1) {
availableUpgrades.push(upg);
}
Expand Down
Loading
Loading