-
Notifications
You must be signed in to change notification settings - Fork 569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Customize response headers with Express middleware #668
Comments
Hi! As a temporary workaround, io.engine.on("headers", (headers, req) => {
if (req.res) { // only for HTTP requests (not during WebSocket upgrade)
helmet()(req, req.res);
}
}); The only problem with the suggestion there is that the WebSocket upgrade does not expose a ServerResponse object, so we would need to create a dummy ServerResponse object and forward any call to the |
In socketio/socket.io#4609 you suggested: io.engine.use(yourMiddleware); What we are using now are two ways to add middlewares, using the same Express middlewares we have. For something like For e.g. authentication middlware we use something like: const authMiddleware = (req, res, next) => {
passport.authenticate('session')(req, res, next);
};
io.of(namespace).use((socket, next) =>
authMiddleware(socket.request, {}, next)
); That works fine. But was mostly for the first part of using helmet() we needed something else. But maybe you are onto something of adding a better way to add generic middleware that works in both scenarios? |
This commit implements middlewares at the Engine.IO level, because Socket.IO middlewares are meant for namespace authorization and are not executed during a classic HTTP request/response cycle. A workaround was possible by using the allowRequest option and the "headers" event, but this feels way cleaner and works with upgrade requests too. Syntax: ```js engine.use((req, res, next) => { // do something next(); }); // with express-session import session from "express-session"; engine.use(session({ secret: "keyboard cat", resave: false, saveUninitialized: true, cookie: { secure: true } }); // with helmet import helmet from "helmet"; engine.use(helmet()); ``` Related: - #668 - #651 - socketio/socket.io#4609 - socketio/socket.io#3933 - a lot of other issues asking for compatibility with express-session
Here we go! Improved support for Express middlewares was added in 24786e7, included in io.engine.use(yourMiddleware); Added in the documentation there: https://socket.io/docs/v4/middlewares/#compatibility-with-express-middleware Please reopen if needed. |
@darrachequesne maybe I am a bit tired now. The example in https://socket.io/docs/v4/middlewares/#compatibility-with-express-middleware shows to use this with: io.engine.use(session({})); For the passport-session and Would then not a better option be to show the usage of https://github.com/helmetjs/helmet as: import session from "express-session";
io.engine.use(helmet()); Maybe I am missing how the |
Even if you use a Socket.IO middleware ( That being said, the example could indeed be improved because we only need to run it once I think: import session from "express-session";
const sessionMiddleware = session({
secret: "keyboard cat",
resave: false,
saveUninitialized: true,
cookie: { secure: true }
});
io.engine.use((req, res, next) => {
if (req._query.sid === undefined) {
// first HTTP request
sessionMiddleware(req, res, next);
} else {
// subsequent HTTP requests
next();
}
}); |
@darrachequesne I see. But then I am not sure the idea of showing how to use sessions with Express middleware as done in https://socket.io/docs/v4/middlewares/#compatibility-with-express-middleware is great. As it could make user use that pattern for authentication when it might not be ideal. It is of course great for the initial HTTP request. Hence why I think showing usage with The rationale I have is that one would want to make the session authentication done for every new socket.io socket. Which is ideally done with I might be entirely incorrect here in my reasoning. My goal is of course to make this as usability friendly as possible for everyone to have authentication logic with socket.io that works the best security-wise. |
Is your feature request related to a problem? Please describe.
A common Express middleware needs an interface like
(req, res, next)
. A common example would behelmet()
which adds securtiy headers in responses.But the new headers introduced in https://socket.io/blog/socket-io-4-1-0/#add-a-way-to-customize-the-response-headers does not get the
res
in the callback:This means we cannot use common Express middleware to add headers properly.
Describe the solution you'd like
I would have wanted this:
Describe alternatives you've considered
Our current solution is this which is a hack we want to replace with the new solution of
io.engine.on("initial_headers"
andio.engine.on("headers"
The text was updated successfully, but these errors were encountered: