
Preflight Request Failed
The error “CORS: preflight request failed” occurs when the browser sends a preflight request (an OPTIONS request) to the server, but the server either does not respond correctly or rejects the request.OPTIONS
Preflight requests are part of the Cross-Origin Resource Sharing (CORS) mechanism and are triggered for certain types of cross-origin requests. Let’s break down why this happens, how to fix it, and best practices for handling preflight requests.
Why Does This Error Occur?
A preflight request is sent by the browser when:
- The request uses HTTP methods other than
[GET, POST, HEAD]
- The request includes custom headers e.g.:
Authorization
Content-Type
- The
Content-Type
header is set to a value other thanapplication/x-www-form-urlencoded
multipart/form-data
text/plain
If the server does not respond to the preflight request with the appropriate CORS headers, the browser will block the actual request and throw the error: “CORS: preflight request failed”.
How to Fix the Error
1. Ensure the Server Responds to Preflight Requests
The server must handle OPTIONS
requests and include the necessary CORS headers in the response. Here’s how to configure this in different server environments:
Example in Node.js (Express):
const express = require('express');
const app = express();
// Handle preflight requests
app.options('/api/data', (req, res) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.send();
});
app.get('/api/data', (req, res) => {
res.json({ message: 'Hello, CORS is enabled!' });
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
Example in Python (Flask):
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/api/data', methods=['GET', 'OPTIONS'])
def handle_data():
if request.method == 'OPTIONS':
response = jsonify()
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type, Authorization')
return response
return jsonify(message="Hello, CORS is enabled!")
if __name__ == '__main__':
app.run(port=3000)
Example in Nginx:
If you’re using Nginx as a reverse proxy, add the following to your configuration:
location /api/ {
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
return 204;
}
proxy_pass http://backend-server;
}
2. Include the Correct Headers in the Preflight Response
The server must include the following headers in the preflight response:
- Access-Control-Allow-Origin: Specifies which origins are allowed e.g.:
*
orhttps://example.com
- Access-Control-Allow-Methods: Lists the HTTP methods allowed for the actual request e.g.:
GET, POST, PUT, DELETE
- Access-Control-Allow-Headers: Lists the headers allowed in the actual request e.g.:
Content-Type, Authorization
Example Preflight Response:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
3. Debugging Preflight Requests
If you’re unsure why the preflight request is failing, inspect the request and response using browser developer tools or a tool like Postman. Look for:
- Missing or incorrect CORS headers in the preflight response.
- Mismatched value of
Access-Control-Allow-Origin
- Incorrect
Access-Control-Allow-Methods
orAccess-Control-Allow-Headers
Real-World Example: Handling Preflight Requests
Scenario:
You have a frontend application hosted on https://frontend.com
that needs to send a PUT request with a custom Authorization header to a backend API hosted on https://backend.com
The backend API does not handle preflight requests correctly, causing the error: “CORS: preflight request failed”.
Solution:
- Update the backend server to handle
OPTIONS
requests and include the necessary CORS headers. - Ensure the
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
headers are correctly set in the preflight response.
Updated Frontend Code:
fetch('https://backend.com/api/data', {
method: 'PUT',
headers: {
'Authorization': 'Bearer token',
'Content-Type': 'application/json'
},
body: JSON.stringify({ key: 'value' })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
Best Practices for Handling Preflight Requests
- Always Handle OPTIONS Requests: Ensure your server responds to
OPTIONS
requests with the correct CORS headers. - Use Specific Origins: Avoid using * for
Access-Control-Allow-Origin
in production. Instead, specify the exact origins that are allowed. - Limit Allowed Methods and Headers: Only allow the HTTP methods and headers that are necessary for your application.
- Test Thoroughly: Use browser developer tools or API testing tools to verify that preflight requests are handled correctly.
Conclusion
The Preflight Request Failed error indicates that the server did not respond correctly to the browser’s CORS preflight request, often due to missing or misconfigured CORS headers. To fix this, ensure that the server properly handles OPTIONS
requests and includes the necessary Access-Control-Allow-*
headers to match the client’s request while maintaining security.