in my server i have a process to create a json web token and set it as a cookie after finding user from mongodb..i just create the token, calculate the cookies expiry, and set the cookie like so:
var d = new Date();
d.setTime(d.getTime() (30 * 24 * 60 * 60 * 1000));
let token = createToken(user.id);
res.cookie("userToken", token, { expires: d });
the problem is sometimes i need to do this process in other routes which is leaving a lot of duplicate code that is harder to change and maintain..i want to create a middleware function that i can reuse where ever i need..i'm thinking of something like so:
function setTokenCookie(user,req,res,next){
var d = new Date();
d.setTime(d.getTime() (30 * 24 * 60 * 60 * 1000));
let token = createToken(user.id);
res.cookie("userToken", token, { expires: d });
next();
}
router.post("/route", (req, res) => {
User.findOne({ email: email }).then(user => {
//some code to handle user here
setTokenCookie(user,req,res,next);
//more code process here
res.sendStatus(200);
}).catch(err => {
res.status(400).send(err.message);
})
})
but this doesn't work..what can i do to implement my goal idea?
EDIT: by "this doesn't work" i mean that i got an error that states that "next" is not a function inside the middleware..i don't know why. when i delete the next() line and try to run the function, the browser doesn't receive the jwt cookie afte the response is received..i don't know why is this happening
CodePudding user response:
You can pass your own callback as the next
argument and the middleware will tell you when it's done that way:
function setTokenCookie(user,req,res,next){
var d = new Date();
d.setTime(d.getTime() (30 * 24 * 60 * 60 * 1000));
let token = createToken(user.id);
res.cookie("userToken", token, { expires: d });
next();
}
router.post("/route", (req, res, next) => {
User.findOne({ email: email }).then(user => {
//some code to handle user here
setTokenCookie(user, req, res, (err) => {
if (err) {
next(err);
} else {
//more code process here
res.sendStatus(200);
}
});
}).catch(err => {
res.status(400).send(err.message);
})
});
Since your middleware is not asynchronous, you could also just factor out the core logic into its own function that you can use multiple places:
function setTokenCookieInternal(user, req, res) {
var d = new Date();
d.setTime(d.getTime() (30 * 24 * 60 * 60 * 1000));
let token = createToken(user.id);
res.cookie("userToken", token, { expires: d });
}
function setTokenCookie(user,req,res,next){
setTokenCookieInternal(user, req, res);
next();
}
And, then use the internal function in your route:
router.post("/route", (req, res) => {
User.findOne({ email: email }).then(user => {
//some code to handle user here
setTokenCookieInternal(user, req, res);
//more code process here
res.sendStatus(200);
}).catch(err => {
res.status(400).send(err.message);
})
});
Or, a third option is you could make your middleware so it can be used either as a function or as middleware based on whether the next
argument is passed or not:
function setTokenCookie(user,req,res,next){
var d = new Date();
d.setTime(d.getTime() (30 * 24 * 60 * 60 * 1000));
let token = createToken(user.id);
res.cookie("userToken", token, { expires: d });
// only call next() if the next argument was passed
if (next) {
next();
}
}
router.post("/route", (req, res) => {
User.findOne({ email: email }).then(user => {
//some code to handle user here
setTokenCookie(user, req, res);
//more code process here
res.sendStatus(200);
}).catch(err => {
res.status(400).send(err.message);
})
});
CodePudding user response:
If you don't want to have a next
function when you run it manually, you can do this:
- Remove the
next
parameter from the function call
setTokenCookie(user,req,res)
- In
setTokenCookie
, only run thenext
function if there is one (last line)
if (next) next();