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!