Fix CORS Vary Origin Header for CDN Caching
In this tutorial, you'll learn about Fix CORS Vary Origin Header for CDN Caching. We cover key concepts, practical examples, and best practices.
When your API returns a dynamic Access-Control-Allow-Origin based on the request's Origin header, a CDN or browser cache may serve a response meant for one origin to a different origin. The Vary: Origin header tells the cache to store separate responses per origin, preventing cross-origin data leaks.
Wrong
The server echoes the request origin dynamically but omits the Vary header.
app.use((req, res, next) => {
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
}
if (req.method === 'OPTIONS') return res.sendStatus(204);
next();
});
Response for https://app.example.com:
Access-Control-Allow-Origin: https://app.example.com
CDN caches this response. When https://admin.example.com makes the same request:
Access-Control-Allow-Origin: https://admin.example.com
But the CDN serves the cached response from the first request:
Access-Control-Allow-Origin: https://app.example.com
The admin app gets a CORS error because the origin does not match.
Right
Add Vary: Origin so the cache stores separate entries per origin.
app.use((req, res, next) => {
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
res.setHeader('Vary', 'Origin');
}
if (req.method === 'OPTIONS') return res.sendStatus(204);
next();
});
Response headers:
Access-Control-Allow-Origin: https://admin.example.com
Vary: Origin
The CDN now treats each origin as a separate cache entry. Both origins receive the correct Access-Control-Allow-Origin value.
With the cors npm package, Vary: Origin is set automatically when using dynamic origins:
const cors = require('cors');
app.use(cors({
origin: (origin, callback) => {
if (allowedOrigins.includes(origin)) {
callback(null, origin);
} else {
callback(null, false);
}
},
}));
Prevention
- Always set
Vary: Originwhen using a dynamicAccess-Control-Allow-Originthat changes per request. - Do not set
Vary: Originwhen usingAccess-Control-Allow-Origin: *or a single fixed origin, as it is unnecessary and reduces cache efficiency. - If you also vary on other headers like
Accept-Encoding, combine them:Vary: Origin, Accept-Encoding. - Test CDN behavior by sending requests from different origins and inspecting the response headers.
- Remember that
Vary: Originreduces cache hit rates because each origin gets its own cached entry.
DodaTech Tools
Doda Browser's network inspector highlights responses that are missing Vary: Origin when a dynamic CORS origin is detected. DodaZIP's CDN configuration audit checks for the correct Vary directives in cached responses. Durga Antivirus Pro's API gateway automatically sets Vary: Origin on all responses with dynamic CORS origins.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro