Return

All tests / src/helpers cors.ts

100% Statements 17/17
90% Branches 9/10
100% Functions 2/2
100% Lines 16/16

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;