ghost
Version:
The professional publishing platform
103 lines (84 loc) • 2.54 kB
JavaScript
const cors = require('cors');
const url = require('url');
const os = require('os');
const urlUtils = require('../../../../shared/url-utils');
const config = require('../../../../shared/config');
let allowlist = [];
const ENABLE_CORS = {origin: true, maxAge: config.get('caching:cors:maxAge')};
const DISABLE_CORS = {origin: false};
/**
* Gather a list of local ipv4 addresses
* @return {Array<String>}
*/
function getIPs() {
const ifaces = os.networkInterfaces();
const ips = [
'localhost'
];
Object.keys(ifaces).forEach((ifname) => {
ifaces[ifname].forEach((iface) => {
// only support IPv4
if (iface.family !== 'IPv4') {
return;
}
ips.push(iface.address);
});
});
return ips;
}
function getUrls() {
const blogHost = url.parse(urlUtils.urlFor('home', true)).hostname;
const adminHost = url.parse(urlUtils.urlFor('admin', true)).hostname;
const urls = [];
urls.push(blogHost);
if (adminHost !== blogHost) {
urls.push(adminHost);
}
return urls;
}
function getAllowlist() {
// This needs doing just one time after init
if (allowlist.length === 0) {
// origins that always match: localhost, local IPs, etc.
allowlist = allowlist.concat(getIPs());
// Trusted urls from config.js
allowlist = allowlist.concat(getUrls());
}
return allowlist;
}
/**
* Checks the origin and enables/disables CORS headers in the response.
* @param {Object} req express request object.
* @param {Function} cb callback that configures CORS.
* @return {null}
*/
function corsOptionsDelegate(req, cb) {
const origin = req.get('origin');
// Request must have an Origin header
if (!origin || origin === 'null') {
return cb(null, DISABLE_CORS);
}
// Origin matches allowlist
if (getAllowlist().indexOf(url.parse(origin).hostname) > -1) {
return cb(null, ENABLE_CORS);
}
return cb(null, DISABLE_CORS);
}
/**
*
* @param {Express.Request} req
* @param {Express.Response} res
* @param {Function} next
*/
const handleCaching = function handleCaching(req, res, next) {
const method = req.method && req.method.toUpperCase && req.method.toUpperCase();
if (method === 'OPTIONS') {
// @NOTE: try to add native support for dynamic 'vary' header value in 'cors' module
res.vary('Origin');
}
next();
};
module.exports = [
handleCaching,
cors(corsOptionsDelegate)
];