Originally posted on cri.dev
I want to share how I maintain my connect / express middlewares for simple HTTP APIs in Node.js
The code snippets below are taken from pomodoro.cc api source code.
Defining the middlewares
Below you can see a simple file containing all middlewares, exported as an array.
In this example the middlewares in use are:
-
cookie-parser
to parse cookies e.g. for sessions -
body-parser
to handle JSON bodies -
cors
to mitigate CORS-related headaches -
morgan
for logging
the order of connect middlewares is important, as it can be seen as a pipeline of handlers, executed one by one.
this is why the handling of CORS requests must happen before parsing cookies or the request body for instance.
const cookieParser = require('cookie-parser') const bodyParser = require('body-parser') const cors = require('cors') const morgan = require('morgan') module.exports = [ morgan(':status\t :method\t :response-time ms\t :date[clf]\t :url\t\t'), cors({ origin: true, methods: ['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'], allowedHeaders: ['x-now-id', 'x-now-trace', 'x-powered-by', 'Origin', 'Accept', 'Content-Type', 'Set-Cookie'], credentials: true }), cookieParser(), bodyParser.json({}), bodyParser.urlencoded({ extended: true }) ]
you can call this file
middlewares.js
to follow along with the code
Using the middlewares
In the following code snippet you can see an example usage of the middlewares, in a bare-bone connect / express application in Node.js
const app = require('express')() const middlewares = require('./middlewares') app.use(...middlewares) app.post('/hello', (req, res) => res.json(`hello ${req.body.name}`)) app.listen(process.env.HTTP_PORT || 3000) console.log('listening on http://localhost:3000')
and run
node index.js
Making a request
Once the server is listening on port 3000
, you can run the following and see the middlewares in action with curl
!
You will get an output similar to this one:
> curl -vv -X POST -H 'Content-Type: application/json' http://localhost:3000/hello --data '{"name": "chris"}' ... ... < HTTP/1.1 200 OK < X-Powered-By: Express < Access-Control-Allow-Credentials: true < Content-Type: application/json; charset=utf-8 < Content-Length: 13 < Vary: Origin < ETag: W/"d-WPAgGvBxJ3QraEI06EWKezzLidE" < Date: Tue, 28 Jan 2020 22:36:18 GMT < Connection: keep-alive < "hello chris"*
Notice the headers Access-Control-Allow-Credentials
?
That's for example where the CORS middleware comes in, that is currently configured to allow credentials for CORS requests.
As you can see in middlewares.js:
... cors({ origin: true, methods: ['HEAD', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'], allowedHeaders: ['x-now-id', 'x-now-trace', 'x-powered-by', 'Origin', 'Accept', 'Content-Type', 'Set-Cookie'], credentials: true }), ...
Let me know on Twitter if you have questions or found better ways to handle middlewares!
Top comments (6)
Really cool! Definitely a better option compared to using 30-odd lines of app.js for middlewares. Does the
...
operator guarantee that the properties of the module's exports will be expanded in the order that they're defined?Absolutely yes 👍
Interesting approach, I've never seen this before. Looks very nice!
Thanks!
Nice article! It's really helpful to make your code clean. Thanks ...
Glad it was helpful!