From 704ac7acf44dd8c579b56e983ef9ea2dab7aa3f1 Mon Sep 17 00:00:00 2001 From: tianrking Date: Thu, 16 Jul 2026 20:20:19 +0800 Subject: [PATCH] fix: support Node 10 query parsing --- packages/engine.io/lib/server.ts | 19 ++++++++++++++++++- packages/engine.io/lib/userver.ts | 4 ++-- packages/engine.io/test/server.js | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/packages/engine.io/lib/server.ts b/packages/engine.io/lib/server.ts index c4f2c30d4c..63464b471c 100644 --- a/packages/engine.io/lib/server.ts +++ b/packages/engine.io/lib/server.ts @@ -166,6 +166,23 @@ function parseSessionId(data: string): string | undefined { } catch (e) {} } +export function parseQuery(params: URLSearchParams): Record { + const query: Record = {}; + + params.forEach((value, key) => { + // Define instead of assigning so a `__proto__` query parameter is kept as + // a regular own property, matching Object.fromEntries(). + Object.defineProperty(query, key, { + value, + enumerable: true, + configurable: true, + writable: true, + }); + }); + + return query; +} + // Object.hasOwn() was introduced in Node.js 16.9 function hasOwn(obj: Record, key: string): boolean { return Object.prototype.hasOwnProperty.call(obj, key); @@ -763,7 +780,7 @@ export class Server extends BaseServer { // try to leverage pre-existing `req._query` (e.g: from connect) if (!req._query) { const url = new URL(req.url, "https://socket.io"); - req._query = Object.fromEntries(url.searchParams.entries()); + req._query = parseQuery(url.searchParams); } } diff --git a/packages/engine.io/lib/userver.ts b/packages/engine.io/lib/userver.ts index 54d34a6030..73f3e5b4e3 100644 --- a/packages/engine.io/lib/userver.ts +++ b/packages/engine.io/lib/userver.ts @@ -1,5 +1,5 @@ import debugModule from "debug"; -import { AttachOptions, BaseServer, Server } from "./server"; +import { AttachOptions, BaseServer, parseQuery, Server } from "./server"; import { HttpRequest, HttpResponse, TemplatedApp } from "uWebSockets.js"; import transports from "./transports-uws"; import { EngineRequest } from "./transport"; @@ -42,7 +42,7 @@ export class uServer extends BaseServer { req.url = req.getUrl(); const params = new URLSearchParams(req.getQuery()); - req._query = Object.fromEntries(params.entries()); + req._query = parseQuery(params); req.headers = {}; req.forEach((key, value) => { diff --git a/packages/engine.io/test/server.js b/packages/engine.io/test/server.js index bbfa860681..4ab8a15ffe 100644 --- a/packages/engine.io/test/server.js +++ b/packages/engine.io/test/server.js @@ -42,6 +42,23 @@ describe("server", () => { }); describe("verification", () => { + it("should support Node.js versions without Object.fromEntries", (done) => { + const fromEntries = Object.fromEntries; + Object.fromEntries = undefined; + + engine = listen((port) => { + request + .get(`http://localhost:${port}/engine.io/`) + .query({ transport: "polling", EIO: 4 }) + .end((err, res) => { + Object.fromEntries = fromEntries; + expect(err).to.be(null); + expect(res.status).to.be(200); + done(); + }); + }); + }); + it("should disallow non-existent transports", (done) => { const partialDone = createPartialDone(done, 2);