Ever wonder why some API calls mysteriously fail in your browser but work fine elsewhere?
Why Preflight requests behavior in Express? - Purpose & Use Cases
Imagine building a web app where your frontend calls an API on a different server. You try to send a request with custom headers or methods like PUT or DELETE.
Before the actual request, the browser sends a special "preflight" request to check if the server allows it.
If you don't handle these preflight requests properly on your server, the browser blocks your real request silently.
This leads to confusing errors and broken features, making debugging very frustrating.
Express can detect and respond to preflight requests automatically, telling the browser it's safe to proceed.
This smooth handshake lets your frontend and backend communicate securely and reliably across domains.
app.use((req, res, next) => {
if (req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type');
return res.sendStatus(200);
}
next();
});const cors = require('cors');
app.use(cors());It enables seamless cross-origin communication by automatically handling browser security checks.
When your React app on localhost calls an Express API on another domain, preflight handling ensures your PUT or DELETE requests work without errors.
Browsers send preflight requests to check permissions before sensitive calls.
Without proper handling, requests fail silently and cause bugs.
Express middleware like CORS simplifies preflight response management.
Practice
Solution
Step 1: Understand preflight request role
A preflight request uses the OPTIONS method to ask the server if the actual request is safe to send.Step 2: Identify what preflight checks
It checks allowed methods and headers to prevent unauthorized cross-origin requests.Final Answer:
To check if the server allows the actual request method and headers before sending it -> Option AQuick Check:
Preflight checks permissions = B [OK]
- Thinking preflight sends actual data
- Confusing preflight with authentication
- Assuming preflight closes connection
Solution
Step 1: Recall HTTP methods in Express
Express provides methods matching HTTP verbs like get, post, options, etc.Step 2: Identify method for preflight
Preflight requests use the OPTIONS method, so Express uses app.options() to handle them.Final Answer:
app.options() -> Option AQuick Check:
OPTIONS method handled by app.options() [OK]
- Using app.get() or app.post() for OPTIONS requests
- Confusing app.use() as handler for OPTIONS
- Not handling OPTIONS method at all
app.options('/data', (req, res) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,POST');
res.sendStatus(204);
});
What will the server respond to an OPTIONS request to '/data'?Solution
Step 1: Analyze headers set in response
The code sets 'Access-Control-Allow-Origin' to '*' allowing any origin, and 'Access-Control-Allow-Methods' to 'GET,POST'.Step 2: Check response status
res.sendStatus(204) sends HTTP status 204 (No Content) with the headers.Final Answer:
Status 204 with headers allowing any origin and GET, POST methods -> Option BQuick Check:
Preflight responds 204 + CORS headers = C [OK]
- Expecting status 200 instead of 204
- Missing CORS headers in response
- Confusing 404 or 500 errors
app.options('/api', (req, res) => {
res.header('Access-Control-Allow-Origin', 'https://example.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT');
res.end();
});
But the browser still blocks the actual request. What is the likely problem?Solution
Step 1: Understand preflight header requirements
If the actual request uses custom headers, the server must respond with Access-Control-Allow-Headers listing them.Step 2: Check code for missing headers
The code does not set Access-Control-Allow-Headers, so browser blocks the request due to missing allowed headers.Final Answer:
Missing Access-Control-Allow-Headers header for custom headers -> Option CQuick Check:
Missing allowed headers header blocks request = D [OK]
- Assuming res.end() causes the block
- Thinking Access-Control-Allow-Origin must be '*' always
- Ignoring missing allowed headers header
Solution
Step 1: Match allowed origin and methods
app.options('/resource', (req, res) => { res.header('Access-Control-Allow-Origin', 'https://trusted.com'); res.header('Access-Control-Allow-Methods', 'GET, POST'); res.header('Access-Control-Allow-Headers', 'X-Custom-Auth'); res.sendStatus(204); }); sets Access-Control-Allow-Origin to 'https://trusted.com' and methods to 'GET, POST' as required.Step 2: Include custom headers and correct status
It includes Access-Control-Allow-Headers for 'X-Custom-Auth' and sends status 204 (No Content), which is correct for preflight.Final Answer:
app.options('/resource', (req, res) => { res.header('Access-Control-Allow-Origin', 'https://trusted.com'); res.header('Access-Control-Allow-Methods', 'GET, POST'); res.header('Access-Control-Allow-Headers', 'X-Custom-Auth'); res.sendStatus(204); }); -> Option DQuick Check:
Correct origin, methods, headers, and 204 status = A [OK]
- Using '*' origin when only one domain allowed
- Missing Access-Control-Allow-Headers for custom headers
- Sending wrong status code like 200 or 404
Ready to prove it?
Pass the test and this pattern moves unknown
