0

I am writing a REST API using express. There are multiple endpoints and each has its own specific router. While each endpoint does specific tasks, there are some operations that are common among all requests like auth, logging, and formatting the result into a common output. These tasks are all performed by middleware on the base router, some before the endpoint router and some after.

//v1Router.js
...
//auth, set common headers, etc
app.use(preHandler)

//route to endpoints
app.use('/endpoint1', endpointRouter1)
app.use('/endpoint2', endpointRouter2)
app.use('/endpoint3', endpointRouter3)

//format and send data
app.use(postHandler)

//catch any errors from the chain
app.use(errorHandler)
//endpointRouter1.js
...
router.get('/people', getPeople)
router.get('/people/:id', getPerson)
router.get('*', handleBadPath)

function getPeople(req, res, next) {
    res.locals.data = /*some data we got from db*/
    next()
}
...

I have implemented this such that all functions of the endpoints are middleware, and data within these endpoints (for example content retrieved from the database) is saved in res.locals as it is in an intermediate state. Then the last piece of middleware before error catching on the base router level (postHandler) formats the contents of res.locals into the documented output, logs overall request-handling stats, and sends it to the user with res.json().

This is causing a problem for me because now I am finding it hard/impossible to use "catch-all" handlers for unsupported routes within the specific endpoints. The above example doesn't work because in endpointRouter1, every request would make it to the catch-all. Each handler above the catch-all does not send the result and end the flow, but instead saves to res.locals and calls next().

With this in mind I'm wondering if there is a best practice for when I should be calling res.json()? Have I implemented a bad approach? Some alternatives I've thought of:

  • Have the results sent from within each endpoint, with each route handler calling a common function to package and send the data.
  • Have the results sent from within each endpoint, and have the postHandler function bound to the response like in this answer

However If my current approach is reasonable for the flow of data through the routers, how can I properly implement a catch-all for improper requests?

JoeBruzek
  • 509
  • 4
  • 16
  • Try `router.all('*', handleBadPath)` – Sándor Bakos Aug 09 '19 at 09:05
  • @SándorBakos that will have the same result as above, all requests will end up being caught by that route – JoeBruzek Aug 09 '19 at 14:38
  • For improper request try Sandor's but `app.all('*', handleBadPath)` in the main JS file where you import all your routes (usually your server file) and make sure it's **the very last** route. Check out this [question and its answers](https://stackoverflow.com/questions/4531900/error-handling-in-express-js). Btw your question is too broad and ambiguous, you got lucky nobody downvoted you or ashamed you (I'm not one of them - just letting you know). Best to keep your question simple, and ask for one thing (trying to be helpful - and for an hour been trying to figure out your question). – Matin Sasan Aug 11 '19 at 02:08

0 Answers0