The Pitfall of Cross-Origin Preflight — Preflight
Recently, some interfaces in my project required cross-origin requests. Here's what I did:
- First, create a new axios instance, which is only responsible for cross-origin requests.
- The new instance reuses the interceptors of the previous instance.
- When the new instance request fails, the error message is CORS.
- Contacted the backend to confirm whether cross-origin was enabled. After getting a positive response, directly using
fetch(url)showed noCORSerror.
Problem Analysis and Conclusion
- Since fetch works but axios (based on XHR) reports an error, it should be an axios configuration issue.
- Discovered that when reusing the request interceptor of axios, additional fields were carried in the request header.
- Because of the extra fields, the browser sends a
preflightrequest before sending the actual request. This preflight request uses theOPTIONSmethod, and only after it succeeds does the actual request get sent. - To allow the preflight to pass, simply adding CORS headers is not enough; the server needs to handle the preflight request separately.
- The following code comes from ChatGPT. I ran a demo myself to try handling the preflight request.
const express = require('express');
const app = express();
// Middleware to handle preflight requests
app.options('*', (req, res) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.status(200).send();
});
// Route to handle actual requests
app.get('/api/data', (req, res) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
// Handle business logic and send response
res.json({ message: 'Hello, world!' });
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});