76 lines
2.7 KiB
JavaScript
76 lines
2.7 KiB
JavaScript
|
|
const fs = require('fs');
|
|||
|
|
const path = require('path');
|
|||
|
|
|
|||
|
|
function parseDomains() {
|
|||
|
|
try {
|
|||
|
|
return {
|
|||
|
|
domains: JSON.parse(process.env.DOMAINS || '[]'),
|
|||
|
|
domainsAllowed: JSON.parse(process.env.DOMAINS_ALLOWED || '[]'),
|
|||
|
|
};
|
|||
|
|
} catch {
|
|||
|
|
return { domains: [], domainsAllowed: [] };
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function createCorsOptions(domains = [], domainsAllowed = [], isProduction = false) {
|
|||
|
|
// 1️⃣ Prepara la lista host ammessi (senza porta)
|
|||
|
|
const baseHosts = isProduction
|
|||
|
|
? domains.flatMap((d) => [d.hostname, `api.${d.hostname}`, `test.${d.hostname}`, `testapi.${d.hostname}`])
|
|||
|
|
: ['localhost', '127.0.0.1'];
|
|||
|
|
|
|||
|
|
const extraHosts = domainsAllowed.map((d) => d.replace(/^https?:\/\//, '').split(':')[0]);
|
|||
|
|
|
|||
|
|
const allowedHosts = [...new Set([...baseHosts, ...extraHosts])];
|
|||
|
|
|
|||
|
|
// 2️⃣ Funzione di validazione origin (accetta qualsiasi porta)
|
|||
|
|
const originValidator = (origin, callback) => {
|
|||
|
|
if (!origin) return callback(null, true); // Postman, curl, ecc.
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const url = new URL(origin);
|
|||
|
|
const host = url.hostname.toLowerCase();
|
|||
|
|
|
|||
|
|
if (allowedHosts.includes(host)) {
|
|||
|
|
// if (!isProduction) console.log(`✅ [CORS OK] ${origin}`);
|
|||
|
|
return callback(null, true);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!isProduction) {
|
|||
|
|
console.warn(`⚠️ [CORS DEV] origin non ammessa: ${origin} (host: ${host})`);
|
|||
|
|
return callback(null, true); // in dev permetti tutto
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.error(`❌ [CORS BLOCKED] ${origin}`);
|
|||
|
|
return callback(new Error(`CORS denied for origin ${origin}`), false);
|
|||
|
|
} catch (err) {
|
|||
|
|
console.error(`❌ [CORS ERROR] parsing origin: ${origin} -> ${err.message}`);
|
|||
|
|
return callback(new Error('CORS denied: invalid origin'), false);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 3️⃣ Restituisce l’oggetto completo per il middleware cors()
|
|||
|
|
return {
|
|||
|
|
origin: originValidator,
|
|||
|
|
credentials: true,
|
|||
|
|
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'],
|
|||
|
|
allowedHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization', 'x-auth', 'x-refrtok'],
|
|||
|
|
exposedHeaders: ['x-auth', 'x-refrtok'],
|
|||
|
|
maxAge: 86400, // 24 ore di caching per la preflight response
|
|||
|
|
preflightContinue: false,
|
|||
|
|
optionsSuccessStatus: 204,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function getCredentials(hostname) {
|
|||
|
|
const key = fs.readFileSync(`/etc/letsencrypt/live/${hostname}/${process.env.PATH_CERT_KEY}`, 'utf8');
|
|||
|
|
const cert = fs.readFileSync(`/etc/letsencrypt/live/${hostname}/${process.env.PATH_SERVER_CRT}`, 'utf8');
|
|||
|
|
return {
|
|||
|
|
key,
|
|||
|
|
cert,
|
|||
|
|
secureProtocol: 'TLSv1_2_method',
|
|||
|
|
secureOptions: require('constants').SSL_OP_NO_SSLv3 | require('constants').SSL_OP_NO_TLSv1,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = { parseDomains, createCorsOptions, getCredentials };
|