CloudFlare and Server Side Whitelisting for CORS
How a Server Explicitly Sets CORS Headers for an HTTP Request
A server explicitly sets CORS headers by including them in the HTTP response to a cross-origin request. These headers instruct the browser whether or not to allow frontend JavaScript from another origin to access the response data.
Example: CORS Headers in an HTTP Response
Access-Control-Allow-Origin: https://example-client.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
How to Set CORS Headers in Different Environments
1. Node.js / Express
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "https://example-client.com");
res.header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE");
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
res.header("Access-Control-Allow-Credentials", "true");
next();
});
Or use the built-in middleware:
const cors = require('cors');
const corsOptions = {
origin: "https://example-client.com",
methods: "GET,POST,PUT,DELETE",
credentials: true
};
app.use(cors(corsOptions));
2. Python / Flask
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app, resources={r"/api/*": {"origins": "https://example-client.com"}}, supports_credentials=True)
3. Apache HTTP Server
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "https://example-client.com"
Header set Access-Control-Allow-Methods "GET,POST,PUT,DELETE"
Header set Access-Control-Allow-Headers "Content-Type, Authorization"
Header set Access-Control-Allow-Credentials "true"
</IfModule>
4. Nginx
location /api/ {
add_header 'Access-Control-Allow-Origin' 'https://example-client.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
add_header 'Access-Control-Allow-Credentials' 'true';
}
Preflight Requests (OPTIONS)
For requests that include custom headers or use non-simple HTTP methods (like PUT
, DELETE
), browsers send a preflight request using OPTIONS
.
To support that, servers should handle OPTIONS
requests and return appropriate CORS headers.
Example in Node.js:
app.options("*", (req, res) => {
res.header("Access-Control-Allow-Origin", "https://example-client.com");
res.header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE");
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
res.sendStatus(204);
});
Security Note
Avoid using:
Access-Control-Allow-Origin: *
if you’re sending cookies or Authorization headers. In such cases, use a specific origin and also set:
Access-Control-Allow-Credentials: true
Using Cloudflare to Maintain a Dynamic Origin Whitelist
If your API is hosted behind Cloudflare, you can use Cloudflare Workers or Cloudflare Gateway Rules to dynamically control and enforce CORS logic at the edge — before the request even reaches your origin server.
Example Using a Cloudflare Worker
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request));
});
const allowedOrigins = [
"https://example-client.com",
"https://admin.example.com"
];
async function handleRequest(request) {
const origin = request.headers.get("Origin");
const response = await fetch(request);
const newHeaders = new Headers(response.headers);
if (allowedOrigins.includes(origin)) {
newHeaders.set("Access-Control-Allow-Origin", origin);
newHeaders.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
newHeaders.set("Access-Control-Allow-Headers", "Authorization, Content-Type");
newHeaders.set("Access-Control-Allow-Credentials", "true");
}
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: newHeaders
});
}
This gives you full control over origin validation and CORS behavior at the network edge, improving performance and offloading logic from your app servers.
You can even maintain the whitelist in a KV store or external API and update it dynamically without redeploying infrastructure.
Leave a Reply