diff --git a/package-lock.json b/package-lock.json index c46fc4801..9332d7397 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5755,14 +5755,6 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, - "node_modules/cookie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", - "engines": { - "node": ">=18" - } - }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -15506,14 +15498,14 @@ } }, "packages/engine.io": { - "version": "6.6.2", + "version": "6.6.3", "license": "MIT", "dependencies": { "@types/cors": "^2.8.12", "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", - "cookie": "~1.0.2", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", @@ -15524,7 +15516,7 @@ } }, "packages/engine.io-client": { - "version": "6.6.2", + "version": "6.6.3", "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", @@ -15549,6 +15541,14 @@ "node": ">=10.0.0" } }, + "packages/engine.io/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "engines": { + "node": ">= 0.6" + } + }, "packages/engine.io/node_modules/debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", diff --git a/packages/engine.io/lib/contrib/cookie.types.d.ts b/packages/engine.io/lib/contrib/cookie.types.d.ts new file mode 100644 index 000000000..78c2b2fe6 --- /dev/null +++ b/packages/engine.io/lib/contrib/cookie.types.d.ts @@ -0,0 +1,162 @@ +// imported from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/b83cf9ef8b044e69f05b2a00aa7c6cb767a9acd2/types/cookie/index.d.ts (now deleted) +/** + * Basic HTTP cookie parser and serializer for HTTP servers. + */ + +/** + * Additional serialization options + */ +export interface CookieSerializeOptions { + /** + * Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.3|Domain Set-Cookie attribute}. By default, no + * domain is set, and most clients will consider the cookie to apply to only + * the current domain. + */ + domain?: string | undefined; + + /** + * Specifies a function that will be used to encode a cookie's value. Since + * value of a cookie has a limited character set (and must be a simple + * string), this function can be used to encode a value into a string suited + * for a cookie's value. + * + * The default function is the global `encodeURIComponent`, which will + * encode a JavaScript string into UTF-8 byte sequences and then URL-encode + * any that fall outside of the cookie range. + */ + encode?(value: string): string; + + /** + * Specifies the `Date` object to be the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.1|`Expires` `Set-Cookie` attribute}. By default, + * no expiration is set, and most clients will consider this a "non-persistent cookie" and will delete + * it on a condition like exiting a web browser application. + * + * *Note* the {@link https://tools.ietf.org/html/rfc6265#section-5.3|cookie storage model specification} + * states that if both `expires` and `maxAge` are set, then `maxAge` takes precedence, but it is + * possible not all clients by obey this, so if both are set, they should + * point to the same date and time. + */ + expires?: Date | undefined; + /** + * Specifies the boolean value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.6|`HttpOnly` `Set-Cookie` attribute}. + * When truthy, the `HttpOnly` attribute is set, otherwise it is not. By + * default, the `HttpOnly` attribute is not set. + * + * *Note* be careful when setting this to true, as compliant clients will + * not allow client-side JavaScript to see the cookie in `document.cookie`. + */ + httpOnly?: boolean | undefined; + /** + * Specifies the number (in seconds) to be the value for the `Max-Age` + * `Set-Cookie` attribute. The given number will be converted to an integer + * by rounding down. By default, no maximum age is set. + * + * *Note* the {@link https://tools.ietf.org/html/rfc6265#section-5.3|cookie storage model specification} + * states that if both `expires` and `maxAge` are set, then `maxAge` takes precedence, but it is + * possible not all clients by obey this, so if both are set, they should + * point to the same date and time. + */ + maxAge?: number | undefined; + /** + * Specifies the `boolean` value for the [`Partitioned` `Set-Cookie`](rfc-cutler-httpbis-partitioned-cookies) + * attribute. When truthy, the `Partitioned` attribute is set, otherwise it is not. By default, the + * `Partitioned` attribute is not set. + * + * **note** This is an attribute that has not yet been fully standardized, and may change in the future. + * This also means many clients may ignore this attribute until they understand it. + * + * More information about can be found in [the proposal](https://github.com/privacycg/CHIPS) + */ + partitioned?: boolean | undefined; + /** + * Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.4|`Path` `Set-Cookie` attribute}. + * By default, the path is considered the "default path". + */ + path?: string | undefined; + /** + * Specifies the `string` to be the value for the [`Priority` `Set-Cookie` attribute][rfc-west-cookie-priority-00-4.1]. + * + * - `'low'` will set the `Priority` attribute to `Low`. + * - `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set. + * - `'high'` will set the `Priority` attribute to `High`. + * + * More information about the different priority levels can be found in + * [the specification][rfc-west-cookie-priority-00-4.1]. + * + * **note** This is an attribute that has not yet been fully standardized, and may change in the future. + * This also means many clients may ignore this attribute until they understand it. + */ + priority?: "low" | "medium" | "high" | undefined; + /** + * Specifies the boolean or string to be the value for the {@link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7|`SameSite` `Set-Cookie` attribute}. + * + * - `true` will set the `SameSite` attribute to `Strict` for strict same + * site enforcement. + * - `false` will not set the `SameSite` attribute. + * - `'lax'` will set the `SameSite` attribute to Lax for lax same site + * enforcement. + * - `'strict'` will set the `SameSite` attribute to Strict for strict same + * site enforcement. + * - `'none'` will set the SameSite attribute to None for an explicit + * cross-site cookie. + * + * More information about the different enforcement levels can be found in {@link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7|the specification}. + * + * *note* This is an attribute that has not yet been fully standardized, and may change in the future. This also means many clients may ignore this attribute until they understand it. + */ + sameSite?: true | false | "lax" | "strict" | "none" | undefined; + /** + * Specifies the boolean value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.5|`Secure` `Set-Cookie` attribute}. When truthy, the + * `Secure` attribute is set, otherwise it is not. By default, the `Secure` attribute is not set. + * + * *Note* be careful when setting this to `true`, as compliant clients will + * not send the cookie back to the server in the future if the browser does + * not have an HTTPS connection. + */ + secure?: boolean | undefined; +} + +/** + * Additional parsing options + */ +export interface CookieParseOptions { + /** + * Specifies a function that will be used to decode a cookie's value. Since + * the value of a cookie has a limited character set (and must be a simple + * string), this function can be used to decode a previously-encoded cookie + * value into a JavaScript string or other object. + * + * The default function is the global `decodeURIComponent`, which will decode + * any URL-encoded sequences into their byte representations. + * + * *Note* if an error is thrown from this function, the original, non-decoded + * cookie value will be returned as the cookie's value. + */ + decode?(value: string): string; +} + +/** + * Parse an HTTP Cookie header string and returning an object of all cookie + * name-value pairs. + * + * @param str the string representing a `Cookie` header value + * @param [options] object containing parsing options + */ +export function parse( + str: string, + options?: CookieParseOptions, +): Record; + +/** + * Serialize a cookie name-value pair into a `Set-Cookie` header string. + * + * @param name the name for the cookie + * @param value value to set the cookie to + * @param [options] object containing serialization options + * @throws {TypeError} when `maxAge` options is invalid + */ +export function serialize( + name: string, + value: string, + options?: CookieSerializeOptions, +): string; diff --git a/packages/engine.io/lib/server.ts b/packages/engine.io/lib/server.ts index b3c708eed..24576b131 100644 --- a/packages/engine.io/lib/server.ts +++ b/packages/engine.io/lib/server.ts @@ -6,7 +6,6 @@ import { EventEmitter } from "events"; import { Socket } from "./socket"; import debugModule from "debug"; import { serialize } from "cookie"; -import type { SerializeOptions } from "cookie"; import { Server as DEFAULT_WS_ENGINE } from "ws"; import type { IncomingMessage, @@ -18,6 +17,7 @@ import type { Duplex } from "stream"; import { WebTransport } from "./transports/webtransport"; import { createPacketDecoderStream } from "engine.io-parser"; import type { EngineRequest } from "./transport"; +import { CookieSerializeOptions } from "./contrib/cookie.types"; const debug = debugModule("engine"); @@ -123,7 +123,7 @@ export interface ServerOptions { * might be used for sticky-session. Defaults to not sending any cookie. * @default false */ - cookie?: (SerializeOptions & { name: string }) | boolean; + cookie?: (CookieSerializeOptions & { name: string }) | boolean; /** * the options that will be forwarded to the cors module */ diff --git a/packages/engine.io/package.json b/packages/engine.io/package.json index 79fd6d30e..582a89c6c 100644 --- a/packages/engine.io/package.json +++ b/packages/engine.io/package.json @@ -35,7 +35,7 @@ "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", - "cookie": "~1.0.2", + "cookie": "~0.7.2", "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1",