Skip to content

Commit d2d753f

Browse files
refactor(sio): align client file matching in Node.js HTTP server
Use the same explicit allowlist of shipped Socket.IO client bundles when serving static files from the Node.js HTTP server.
1 parent dfb5ab3 commit d2d753f

2 files changed

Lines changed: 62 additions & 22 deletions

File tree

packages/socket.io/lib/index.ts

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ import corsMiddleware from "cors";
5252
const debug = debugModule("socket.io:server");
5353

5454
const clientVersion = require("../package.json").version;
55-
const dotMapRegex = /\.map/;
5655

5756
const CLIENT_FILES = new Set([
5857
"socket.io.esm.min.js",
@@ -285,7 +284,6 @@ export class Server<
285284
private readonly opts: Partial<ServerOptions>;
286285
private eio: Engine;
287286
private _path: string;
288-
private clientPathRegex: RegExp;
289287

290288
/**
291289
* @private
@@ -428,12 +426,6 @@ export class Server<
428426

429427
this._path = v!.replace(/\/$/, "");
430428

431-
const escapedPath = this._path.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
432-
this.clientPathRegex = new RegExp(
433-
"^" +
434-
escapedPath +
435-
"/socket\\.io(\\.msgpack|\\.esm)?(\\.min)?\\.js(\\.map)?(?:\\?|$)",
436-
);
437429
return this;
438430
}
439431

@@ -631,32 +623,39 @@ export class Server<
631623
const evs = srv.listeners("request").slice(0);
632624
srv.removeAllListeners("request");
633625
srv.on("request", (req, res) => {
634-
if (this.clientPathRegex.test(req.url!)) {
635-
if (this._corsMiddleware) {
636-
this._corsMiddleware(req, res, () => {
637-
this.serve(req, res);
638-
});
639-
} else {
640-
this.serve(req, res);
641-
}
642-
} else {
643-
for (let i = 0; i < evs.length; i++) {
644-
evs[i].call(srv, req, res);
626+
if (req.url.startsWith(this._path)) {
627+
const filename = this.extractFilename(req.url);
628+
if (CLIENT_FILES.has(filename)) {
629+
if (this._corsMiddleware) {
630+
this._corsMiddleware(req, res, () => {
631+
this.serve(filename, req, res);
632+
});
633+
} else {
634+
this.serve(filename, req, res);
635+
}
636+
return;
645637
}
646638
}
639+
for (let i = 0; i < evs.length; i++) {
640+
evs[i].call(srv, req, res);
641+
}
647642
});
648643
}
649644

650645
/**
651646
* Handles a request serving of client source and map
652647
*
648+
* @param filename
653649
* @param req
654650
* @param res
655651
* @private
656652
*/
657-
private serve(req: IncomingMessage, res: ServerResponse): void {
658-
const filename = req.url!.replace(this._path, "").replace(/\?.*$/, "");
659-
const isMap = dotMapRegex.test(filename);
653+
private serve(
654+
filename: string,
655+
req: IncomingMessage,
656+
res: ServerResponse,
657+
): void {
658+
const isMap = filename.endsWith(".map");
660659
const type = isMap ? "map" : "source";
661660

662661
// Per the standard, ETags must be quoted:

packages/socket.io/test/server-attachment.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,47 @@ describe("server attachment", () => {
190190
});
191191
});
192192

193+
describe("static files", () => {
194+
let io: Server;
195+
let port: number;
196+
197+
beforeEach(() => {
198+
io = new Server(0);
199+
port = getPort(io);
200+
});
201+
202+
afterEach(() => {
203+
io.close();
204+
});
205+
206+
it("should serve socket.io.js", async () => {
207+
const res = await fetch(
208+
`http://localhost:${port}/socket.io/socket.io.js`,
209+
);
210+
211+
expect(res.status).to.be(200);
212+
expect(res.headers.get("content-type")).to.be(
213+
"application/javascript; charset=utf-8",
214+
);
215+
});
216+
217+
it("should not serve unknown files from the Socket.IO path", async () => {
218+
const res = await fetch(
219+
`http://localhost:${port}/socket.io/socket.io.esm.js`,
220+
);
221+
222+
expect(res.status).to.be(400);
223+
});
224+
225+
it("should return 404 for mismatching path", async () => {
226+
const res = await fetch(
227+
`http://localhost:${port}/abcdefghij/socket.io.js`,
228+
);
229+
230+
expect(res.status).to.be(404);
231+
});
232+
});
233+
193234
describe("port", () => {
194235
it("should be bound", (done) => {
195236
const io = new Server(0);

0 commit comments

Comments
 (0)