ggop213's picture
fix(cors): allow *.vercel.app origins and update package-lock.json
557a65c
Raw History Blame Contribute Delete
2.45 kB
import type { VercelRequest, VercelResponse } from '@vercel/node';
export type ApiHandler = (req: VercelRequest, res: VercelResponse) => Promise<void>;
function resolveCorsOrigin(req: VercelRequest): string {
const requestOrigin = typeof req.headers.origin === 'string' ? req.headers.origin.trim() : '';
const ALLOWED_ORIGINS = [
'https://getcert.eu.cc',
'https://verify.getcert.eu.cc',
'https://getcert.vercel.app',
'http://localhost:5173',
'http://localhost:3000',
'http://localhost:3001',
];
if (
requestOrigin &&
(ALLOWED_ORIGINS.includes(requestOrigin) ||
requestOrigin.endsWith('.getcert.eu.cc') ||
requestOrigin.endsWith('.vercel.app'))
) {
return requestOrigin;
}
const configured = (process.env.APP_ORIGIN || '').trim();
if (configured && !configured.includes('hf.space')) {
return configured;
}
return 'https://getcert.eu.cc';
}
export function applyCors(req: VercelRequest, res: VercelResponse): void {
const origin = resolveCorsOrigin(req);
res.setHeader('Vary', 'Origin');
res.setHeader('Access-Control-Allow-Origin', origin);
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
res.setHeader(
'Access-Control-Allow-Headers',
'Content-Type, Authorization, x-admin-review-secret, x-payment-review-secret'
);
}
export function withCors(handler: ApiHandler): ApiHandler {
return async (req, res) => {
applyCors(req, res);
if (req.method === 'OPTIONS') {
res.status(200).end();
return;
}
await handler(req, res);
};
}
export function assertMethod(req: VercelRequest, res: VercelResponse, method: 'GET' | 'POST'): boolean {
if (req.method === 'HEAD' && method === 'GET') {
return true;
}
if (req.method !== method) {
res.status(405).json({ success: false, error: `Method ${req.method} not allowed` });
return false;
}
return true;
}
export function parseJsonBody<T>(req: VercelRequest): T {
if (!req.body) {
return {} as T;
}
if (typeof req.body === 'string') {
return JSON.parse(req.body) as T;
}
return req.body as T;
}
export function ok(res: VercelResponse, payload: unknown): void {
res.status(200).json({ success: true, data: payload });
}
export function fail(res: VercelResponse, status: number, error: string, details?: unknown): void {
res.status(status).json({
success: false,
error,
details: details ?? null,
});
}