diff --git a/packages/engine.io/lib/transports-uws/polling.ts b/packages/engine.io/lib/transports-uws/polling.ts index ba49015c6..0e272f38b 100644 --- a/packages/engine.io/lib/transports-uws/polling.ts +++ b/packages/engine.io/lib/transports-uws/polling.ts @@ -53,9 +53,9 @@ export class Polling extends Transport { // remove the reference to the ServerResponse object (as the first request of the session is kept in memory by default) req.res = null; - if (req.getMethod() === "get") { + if (req.method === "GET") { this.onPollRequest(req, res); - } else if (req.getMethod() === "post") { + } else if (req.method === "POST") { this.onDataRequest(req, res); } else { res.writeStatus("500 Internal Server Error"); diff --git a/packages/engine.io/lib/userver.ts b/packages/engine.io/lib/userver.ts index 76ecc9911..001755b51 100644 --- a/packages/engine.io/lib/userver.ts +++ b/packages/engine.io/lib/userver.ts @@ -181,6 +181,11 @@ export class uServer extends BaseServer { req.res = res; + // the uWS.HttpRequest object cannot be accessed once the handler has returned (e.g. with an asynchronous middleware or allowRequest() function) + const secWebSocketKey = req.getHeader("sec-websocket-key"); + const secWebSocketProtocol = req.getHeader("sec-websocket-protocol"); + const secWebSocketExtensions = req.getHeader("sec-websocket-extensions"); + const callback = async (errorCode, errorContext) => { if (errorCode !== undefined) { this.emit("connection_error", { @@ -237,22 +242,24 @@ export class uServer extends BaseServer { this.emit("headers", additionalHeaders, req); - // calling writeStatus() triggers the flushing of any header added in a middleware - req.res.writeStatus("101 Switching Protocols"); + res.cork(() => { + // calling writeStatus() triggers the flushing of any header added in a middleware + req.res.writeStatus("101 Switching Protocols"); - Object.keys(additionalHeaders).forEach((key) => { - req.res.writeHeader(key, additionalHeaders[key]); - }); + Object.keys(additionalHeaders).forEach((key) => { + req.res.writeHeader(key, additionalHeaders[key]); + }); - res.upgrade( - { - transport, - }, - req.getHeader("sec-websocket-key"), - req.getHeader("sec-websocket-protocol"), - req.getHeader("sec-websocket-extensions"), - context, - ); + res.upgrade( + { + transport, + }, + secWebSocketKey, + secWebSocketProtocol, + secWebSocketExtensions, + context, + ); + }); }; this._applyMiddlewares(req, res, (err) => { diff --git a/packages/engine.io/test/middlewares.js b/packages/engine.io/test/middlewares.js index 60e1cc6b2..69f76fac7 100644 --- a/packages/engine.io/test/middlewares.js +++ b/packages/engine.io/test/middlewares.js @@ -56,6 +56,55 @@ describe("middlewares", () => { }); }); + it("should apply an asynchronous middleware (polling)", (done) => { + const engine = listen((port) => { + engine.use((req, res, next) => { + res.setHeader("foo", "bar"); + setTimeout(next, 10); + }); + + 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 an asynchronous middleware (websocket)", (done) => { + const engine = listen((port) => { + engine.use((req, res, next) => { + res.setHeader("foo", "bar"); + setTimeout(next, 10); + }); + + 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;