Home > OS >  call middleware inside express controller
call middleware inside express controller

Time:09-01

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:

  1. Remove the next parameter from the function call
setTokenCookie(user,req,res)
  1. In setTokenCookie, only run the next function if there is one (last line)
if (next) next();
  • Related