Skip to content
Advertisement

In express.js, when to use a middleware and when to use a regular function?

I am making a login authentication module using a regular function in my project. However, I see many developers online using middleware to achieve the same purpose. I am so confused about when to use middleware and when to use a normal function. In general, when is it appropriate to use middleware, does it somehow related to some specific scenarios? I want to know if there is any pattern so that I can establish good coding practices.

I tried to make the same authentication module by using middlewares and it behaves exactly the same as expected. I can always pass the (req, res) parameters to a regular function, so why don’t I just use a regular function?

Advertisement

Answer

I can always pass the (req, res) parameters to a regular function, so why don’t I just use a regular function?

You totally can. But middleware is actually less code. I’m thinking in terms of the below example:

// middleware example
const authMiddleware = async (req,res,next) => {
     try {
       ... do some stuff
       next()
     } catch(err) {
       // handle specific errors, 401, 403, etc
       next(err)
     }
}


const handler = (req,res) => {
   ... handle the request
}


app.use('path',authMiddleware,handler)

and this:

// function example
const authFn = async (req,res) => {
    // ... do some stuff without calling next
}



const handler = async (req,res,next) => {
     try {
       await authFn(req,res)
     } catch(err) {
       // handle specific errors, 401, 403, etc
       return next(err)
     }

     ... handle the request
}


app.use('path',handler)

In the above example, when using a function you’d have to handle errors in each authenticated route (there’s probably more than one) whereas with middleware you can just write it once and use it on all your authenticated routes.

Middleware gets to be an even better separator of concerns when you do stuff like this:

const requirePermissions = (requiredPermissions) => async (req,res,next) => {
     try {
       // evaluate the user against the required permissions
       next()
     } catch(err) {
       next(err)
     }
}

app.use('/somePath', requirePermissions(perm1,perm2), handler)
app.use('/someOtherPath', requirePermissions(perm3,perm4), handler)

As it makes your middleware even more reusable among routes.

Middleware’s awesome.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement