Reputation: 504
If I enable CORS for all routes, the request from the frontend (https://localhost:3000
) works and gets the correct request headers.
const express = require('express');
const cors = require('cors');
var app = express();
app.use(cors());
app.post('/api/submitEmail', () => console.log('yay'));
If I enable CORS on the individual route, exactly as the docs layout, I get the CORS error in the console
app.post('/api/submitEmail', cors(), () => console.log('booooo'));
Error:
Access to XMLHttpRequest at 'http://localhost:8000/api/submitEmail' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
What am I missing?
The entire request from the frontend below
const api =
process.env.NODE_ENV === "development"
? "http://localhost:8000"
: MY_PROD_URL;
const user = {
email
};
axios.post(`${api}/api/submitEmail`, { user }).then(res => {
setIsLoading(false);
setValidationMessage(res.data);
});
Upvotes: 6
Views: 1348
Reputation: 822
I had the same problem and @jfriend00 answer helped me. You just need to include the initial options for the express app:
app.options('/this_is_your_cors_route', cors())
And then your cors route will work:
app.post('/this_is_your_cors_route', cors(), (req, res) => {});
Here are the docs for this issue: https://github.com/expressjs/cors#enabling-cors-pre-flight
Upvotes: 6
Reputation: 708056
You don't show us the details of the actual request, but if the request contains certain special conditions, then the browser will attempt to preflight the request with an OPTIONS request before it issues the POST. When you insert the cors()
call only in the app.post()
route handler, then the OPTIONS request is not handled and if this particular cross origin request is the type that triggers an OPTIONS pre-flight, then because you don't handle it, the request will fail.
You can address that by adding this:
app.options('/api/submitEmail', cors(), (req, res) => res.send());
As this will handle the OPTIONS pre-flight for that specific route.
You can read about what a "simple request" is here. Anything other than a simple request requires the OPTIONS pre-flight. It can be as simple as setting a single custom header or a content-type that isn't allowed in the simple request and that will trigger the OPTIONS pre-flight.
When you did app.use(cors());
, that handled the pre-flight OPTIONS request for you automatically since all HTTP verbs get sent to app.use()
handlers and the cors()
middleware handler supports doing the right thing for an OPTIONS request.
Also, in your POST request handler, you NEED to send a response or the client will just sit there waiting for a response and eventually time out.
Upvotes: 2