Fixing CORS Pre-Flight Errors on Your Express.js API

Use Case: Making your Express API accessible to receive requests.

Building an API in Express and not able to fetch data?

Trying to submit a form via a POST request and getting CORS Pre-Flight errors in the console?

That can be frustrating - especially when you see an array of questions resolved by answers in Stack Overflow that don't seem to be working for you.

My issues began when I built a React frontend fetching data from an Express.js API. The React application sends both GET and POST http requests to the API and only now do I realize that the POST requests required an additional step.

Fetching a GET request with Express

To fetch data via a GET request from Express to my React application, all I needed was a route middleware function that set the Access-Control headers for the page:

JavaScript

const headers = (req, res, next) => {
	const origin = (req.headers.origin == 'http://localhost:3000') ? 'http://localhost:3000' : 'https://mywebsite.com'
	res.setHeader('Access-Control-Allow-Origin', origin)
	res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE')
	res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type')
	res.setHeader('Access-Control-Allow-Credentials', true)
	next()
}

module.exports = headers

I would then simply reference the middleware in my route function:

JavaScript

router.get('/contact', headers, (req, res) => {
	...
	res.send(req.args)
})

Done. I could receive data all day with this setup. But the problem came with sending data back to the API with a POST request ...

Fetching a POST request with Express

What I learned was that certain CORS requests are considered "complex" and require an initial options request known as a pre-flight request. From my understanding, POST requests didn't fall within this categorization (DELETE requests are more common). However, my Express application did consider it to be complex and was therefore blocking it.

The simplest way to solve this and send a pre-flight request was via the CORS Node.js package (NPM ) - npm i cors and assigning it as middleware for the POST route:

JavaScript

const cors = require('cors')

router.post('/contact', cors(), headers, (req, res) => {
	...

The headers middleware is still required to be sent along with the actual POST request. And this solved my issue.

The CORS module can be customized, but the default configuration worked in my case.

JSON

{
	"origin": "*",
	"methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
	"preflightContinue": false,
	"optionsSuccessStatus": 204
}

Hopefully this solved your problem. If not, reach out to my on Twitter below!

Tweet me @tylerewillis

Or send an email:

And support me on Patreon