const listen = require("./common").listen; const expect = require("expect.js"); const request = require("superagent"); const { WebSocket } = require("ws"); const helmet = require("helmet"); const session = require("express-session"); const { ClientSocket } = require("./common"); describe("middlewares", () => { it("should apply middleware (polling)", (done) => { const engine = listen((port) => { engine.use((req, res, next) => { res.setHeader("foo", "bar"); next(); }); request .get(`http://localhost:${port}/engine.io/`) .query({ EIO: 4, transport: "polling" }) .end((err, res) => { expect(err).to.be(null); expect(res.status).to.eql(200); expect(res.headers["foo"]).to.eql("bar"); if (engine.httpServer) { engine.httpServer.close(); } done(); }); }); }); it("should apply middleware (websocket)", (done) => { const engine = listen((port) => { engine.use((req, res, next) => { res.setHeader("foo", "bar"); next(); }); const socket = new WebSocket( `ws://localhost:${port}/engine.io/?EIO=4&transport=websocket`, ); socket.on("upgrade", (res) => { expect(res.headers["foo"]).to.eql("bar"); if (engine.httpServer) { engine.httpServer.close(); } done(); }); socket.on("open", () => { socket.close(); }); }); }); it("should apply all middlewares in order", (done) => { const engine = listen((port) => { let count = 0; engine.use((req, res, next) => { expect(++count).to.eql(1); next(); }); engine.use((req, res, next) => { expect(++count).to.eql(2); next(); }); engine.use((req, res, next) => { expect(++count).to.eql(3); next(); }); request .get(`http://localhost:${port}/engine.io/`) .query({ EIO: 4, transport: "polling" }) .end((err, res) => { expect(err).to.be(null); expect(res.status).to.eql(200); if (engine.httpServer) { engine.httpServer.close(); } done(); }); }); }); it("should end the request (polling)", function (done) { if (process.env.EIO_WS_ENGINE === "uws") { return this.skip(); } const engine = listen((port) => { engine.use((req, res, _next) => { res.writeHead(503); res.end(); }); engine.on("connection", () => { done(new Error("should not happen")); }); request .get(`http://localhost:${port}/engine.io/`) .query({ EIO: 4, transport: "polling" }) .end((err, res) => { expect(err).to.be.an(Error); expect(res.status).to.eql(503); if (engine.httpServer) { engine.httpServer.close(); } done(); }); }); }); it("should end the request (websocket)", (done) => { const engine = listen((port) => { engine.use((req, res, _next) => { res.writeHead(503); res.end(); }); engine.on("connection", () => { done(new Error("should not happen")); }); const socket = new WebSocket( `ws://localhost:${port}/engine.io/?EIO=4&transport=websocket`, ); socket.addEventListener("error", () => { if (engine.httpServer) { engine.httpServer.close(); } done(); }); }); }); it("should work with helmet (polling)", (done) => { const engine = listen((port) => { engine.use(helmet()); request .get(`http://localhost:${port}/engine.io/`) .query({ EIO: 4, transport: "polling" }) .end((err, res) => { expect(err).to.be(null); expect(res.status).to.eql(200); expect(res.headers["x-download-options"]).to.eql("noopen"); expect(res.headers["x-content-type-options"]).to.eql("nosniff"); if (engine.httpServer) { engine.httpServer.close(); } done(); }); }); }); it("should work with helmet (websocket)", (done) => { const engine = listen((port) => { engine.use(helmet()); const socket = new WebSocket( `ws://localhost:${port}/engine.io/?EIO=4&transport=websocket`, ); socket.on("upgrade", (res) => { expect(res.headers["x-download-options"]).to.eql("noopen"); expect(res.headers["x-content-type-options"]).to.eql("nosniff"); if (engine.httpServer) { engine.httpServer.close(); } done(); }); socket.on("open", () => { socket.close(); }); }); }); it("should work with express-session (polling)", (done) => { const engine = listen((port) => { engine.use( session({ secret: "keyboard cat", resave: false, saveUninitialized: true, cookie: {}, }), ); request .get(`http://localhost:${port}/engine.io/`) .query({ EIO: 4, transport: "polling" }) .end((err, res) => { expect(err).to.be(null); // expect(res.status).to.eql(200); expect(res.headers["set-cookie"][0].startsWith("connect.sid=")).to.be( true, ); if (engine.httpServer) { engine.httpServer.close(); } done(); }); }); }); it("should work with express-session (websocket)", (done) => { const engine = listen((port) => { engine.use( session({ secret: "keyboard cat", resave: false, saveUninitialized: true, cookie: {}, }), ); const socket = new WebSocket( `ws://localhost:${port}/engine.io/?EIO=4&transport=websocket`, ); socket.on("upgrade", (res) => { expect(res.headers["set-cookie"][0].startsWith("connect.sid=")).to.be( true, ); if (engine.httpServer) { engine.httpServer.close(); } done(); }); socket.on("open", () => { socket.close(); }); }); }); it("should fail on errors (polling)", (done) => { const engine = listen((port) => { engine.use((req, res, next) => { next(new Error("will always fail")); }); request .get(`http://localhost:${port}/engine.io/`) .query({ EIO: 4, transport: "polling" }) .end((err, res) => { expect(err).to.be.an(Error); expect(res.status).to.eql(400); if (engine.httpServer) { engine.httpServer.close(); } done(); }); }); it("should fail on errors (websocket)", (done) => { const engine = listen((port) => { engine.use((req, res, next) => { next(new Error("will always fail")); }); engine.on("connection", () => { done(new Error("should not connect")); }); const socket = new WebSocket( `ws://localhost:${port}/engine.io/?EIO=4&transport=websocket`, ); socket.addEventListener("error", () => { if (engine.httpServer) { engine.httpServer.close(); } done(); }); }); }); }); it("should not be receiving data when getting a message longer than maxHttpBufferSize when polling (with a middleware)", (done) => { const opts = { allowUpgrades: false, transports: ["polling"], maxHttpBufferSize: 5, }; const engine = listen(opts, (port) => { engine.use((req, res, next) => { next(); }); const socket = new ClientSocket(`ws://localhost:${port}`); engine.on("connection", (conn) => { conn.on("message", () => { done(new Error("Test invalidation (message is longer than allowed)")); }); }); socket.on("open", () => { socket.send("aasdasdakjhasdkjhasdkjhasdkjhasdkjhasdkjhasdkjha"); }); socket.on("close", (reason) => { done(); }); }); }); });