Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 18x 25x 51x 51x 51x 1x 50x 48x 51x 51x 51x 51x 1x 1x 50x 25x | import type { NextApiRequest, NextApiResponse, NextApiHandler } from 'next';
const allowCors =
<T extends NextApiHandler>(fn: T) =>
async (req: NextApiRequest, res: NextApiResponse) => {
// Only allow specific origins in production
const allowedOrigins =
process.env.NODE_ENV === 'production'
? [process.env.NEXT_PUBLIC_DOMAIN || 'https://xabierlameiro.com']
: ['http://localhost:3000', 'https://localhost:3000'];
const origin = req.headers.origin;
if (origin && allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
} else if (process.env.NODE_ENV !== 'production') {
res.setHeader('Access-Control-Allow-Origin', '*');
}
// Every API route is read-only
res.setHeader('Access-Control-Allow-Methods', 'GET,OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Accept, Content-Type');
// The allowlist above reflects the request's Origin into the response, and every route now
// sets a `public, s-maxage=...` Cache-Control (SDD-L02). Without `Vary: Origin` a CDN keys
// those entries on the URL alone and can serve a response bearing one origin's
// Access-Control-Allow-Origin to a request from another. Not exploitable while the production
// allowlist has exactly one entry — every cached value is identical — but it becomes live the
// moment a second origin is added, which is precisely when nobody would think to look here.
res.setHeader('Vary', 'Origin');
if (req.method === 'OPTIONS') {
res.status(200).end();
return;
}
return await fn(req, res);
};
export default allowCors;
|