I have an express
server ("express": "^4.19.2"
) set up and use this custom function to add response headers:
const allowCORS = (req: Request, res: Response, next: NextFunction): void => {
const origin = req.get('origin');
console.log('origin in allowCORS', origin);
res.setHeader("Access-Control-Allow-Origin", origin || '*');
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
if (req.method === 'OPTIONS') {
res.sendStatus(200);
} else {
next();
}
};
In my route I do:
app.get("/", allowCORS, (req: Request, res: Response) => {
res.send({response: "My root route"});
});
It works perfectly fine for all requests, except the prefleight request.
When I test a preflight request I get the status 200 but not the headers.
Here is my curl output:
>curl -i -X OPTIONS -H "Origin: https://some-frontend-application.com" -H "Access-Control-Request-Method: GET" -H "Access-Control-Request-Headers: Origin, X-Requested-With, Content-Type, Accept" http://localhost:3001/
HTTP/1.1 200 OK
X-Powered-By: Express
Allow: GET,HEAD
Content-Type: text/html; charset=utf-8
Content-Length: 8
ETag: W/"8-ZRAf8oNBS3Bjb/SU2GYZCmbtmXg"
Date: Wed, 14 Aug 2024 18:35:52 GMT
Connection: keep-alive
Keep-Alive: timeout=5
When I enable cors()
for all routes:
import cors from 'cors';
app.use(cors())
I get the response headers for the preflight request:
>curl -i -X OPTIONS -H "Origin: https://some-frontend-application.com" -H "Access-Control-Request-Method: GET" -H "Access-Control-Request-Headers: Origin, X-Requested-With, Content-Type, Accept" http://localhost:3001/
HTTP/1.1 204 No Content
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Vary: Access-Control-Request-Headers
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Content-Length: 0
Date: Wed, 14 Aug 2024 18:35:36 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Also, for every other request the headers are set:
>curl -i -H "Origin: https://some-frontend-app.com" http://loca
lhost:3001/
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: https://some-frontend-app.com
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Content-Type: application/json; charset=utf-8
Content-Length: 42
ETag: W/"2a-nitr8TuSR9eKLHj8wLq+IXZALnA"
Date: Wed, 14 Aug 2024 18:43:01 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Any idea how to fix this for the preflight?
Notice this line of code you have written, problem lies here.
app.get("/", allowCORS, (req: Request, res: Response) => {
res.send({response: "My root route"});
});
Its the method app.get
, your allowCors
middleware runs only during GET
request but not during preflight. If you use cors
package here result will be same.
Thus this line never true.
if (req.method === 'OPTIONS') {
Include middleware during preflight
app.options('/test', allowCors)
app.get('/test', allowCors, handleTest) // or app.get('/test', cors(), handleTest)
much better solution is app.route()
(same as above but in elegant way)
app.route('/test')
.all(allowCors) // or .all(cors())
.get(handleTest)
app.use(allowCors)