It's time to deal deeper with middleware and create a way to allow the users from our framework to create their routes separately from the main app object.
Let's get started!
Global Middlewares
src/app.js
// (1)
const middlewaresForAll = []
// (2)
const use = (path, ...middlewares) => {
const possiblePaths = [path + '/GET', path + '/POST', path + '/PUT', path + '/PATCH', path + '/DELETE']
possiblePaths.forEach(route => {
const middlewaresAndControllers = routes.get(route) || []
if (middlewaresAndControllers.length) {
routes.set(route, [...middlewares, ...middlewaresAndControllers])
}
})
}
// (3)
const useAll = (...middlewares) => {
middlewaresForAll.push(...middlewares)
}
const serverHandler = async (request, response) => {
const sanitizedUrl = sanitizeUrl(request.url, request.method)
const match = matchUrl(sanitizedUrl)
if (match) {
const middlewaresAndControllers = routes.get(match)
// (4)
await dispatchChain(request, response,
[requestDecorator.bind(null, routes.keys()), responseDecorator, ...middlewaresForAll, ...middlewaresAndControllers])
} else {
response.statusCode = 404
response.end('Not found')
}
}
From the code sessions above
1 - We need an array to store the middlewares that should be applied for all routes.
2 - The use
function is responsible to add middleware for a specified path independently of the used method.
3 - The useAll
is a way to add middleware to the middleware store.
4 - Now we can modify our serverHandler
function to apply the array of middlewares for all routes.
Modular Router
It is a mini-app that we can include in our main application.
src/router.js
const Router = () => {
const routes = new Map()
const middlewaresForAll = []
const getRoutes = () => {
return routes
}
const getMiddlewaresForAll = () => {
return middlewaresForAll
}
const useAll = (...middlewares) => {
middlewaresForAll.push(...middlewares)
}
const use = (path, ...middlewares) => {
const possiblePaths = [path + '/GET', path + '/POST', path + '/PUT', path + '/PATCH', path + '/DELETE']
possiblePaths.forEach(route => {
const middlewaresAndControllers = routes.get(route) || []
if (middlewaresAndControllers.length) {
routes.set(route, [...middlewares, ...middlewaresAndControllers])
}
})
}
const get = (path, ...handlers) => {
const middlewaresAndControllers = routes.get(`${path}/GET`) || []
routes.set(`${path}/GET`, [...middlewaresAndControllers, ...handlers])
}
const post = (path, ...handlers) => {
const middlewaresAndControllers = routes.get(`${path}/POST`) || []
routes.set(`${path}/POST`, [...middlewaresAndControllers, ...handlers])
}
const put = (path, ...handlers) => {
const middlewaresAndControllers = routes.get(`${path}/PUT`) || []
routes.set(`${path}/PUT`, [...middlewaresAndControllers, ...handlers])
}
const patch = (path, ...handlers) => {
const middlewaresAndControllers = routes.get(`${path}/PATCH`) || []
routes.set(`${path}/PATCH`, [...middlewaresAndControllers, ...handlers])
}
const del = (path, ...handlers) => {
const middlewaresAndControllers = routes.get(`${path}/DELETE`) || []
routes.set(`${path}/DELETE`, [...middlewaresAndControllers, ...handlers])
}
return {
get,
post,
put,
patch,
del,
use,
useAll,
getRoutes,
getMiddlewaresForAll
}
}
module.exports = Router
That is all we have in the main app, the only difference we need to return routes
and middlewaresForAll
too.
To use our modular router we need to get the router handlers and combine them with existent routes.
src/app.js
const useRouter = (path, router) => {
const routerRoutes = router.getRoutes()
const middlewaresFromRouter = router.getMiddlewaresForAll()
const existentHandlers = routes.get(path) || []
routerRoutes.forEach((middlewares, key) => {
routes.set(`${path + key}`, [...existentHandlers, ...middlewaresFromRouter, ...middlewares])
})
}
Testing
router.get('/users', (req, res) => res.end('User route from router instance'))
router.get('/admins', (req, res) => res.end('Admins route'))
router.useAll((req, res, next) => {
console.log('middleware for router instance /admins and /users')
next()
})
router.use('/users', (req, res, next) => {
console.log('middleware for /users')
next()
})
router.use('/admins', (req, res, next) => {
console.log('middleware for /admins')
next()
})
app.useRouter('', router)
app.use('/admins', (req, res, next) => {
console.log('middleware for all admins routes')
next()
})
app.useAll((req, res, next) => {
console.log('middleware for all routes')
next()
})
If I try to access admins
route running in a terminal this command:
curl --location 'localhost:3000/admins'
You must see in the console something like that:
middleware for all routes
middleware for all admins routes
middleware for router instance /admins and /users
middleware for /admins
That's all for now. You can see the entire code here
In the next tutorial, I will show how to serve static files.
See you soon!
Top comments (0)