4fa4f13558
Co-authored-by: iamlukethedev <iamlukethedev@users.noreply.github.com>
85 lines
2.1 KiB
JavaScript
85 lines
2.1 KiB
JavaScript
const net = require("node:net");
|
|
|
|
const normalizeHost = (host) => {
|
|
let raw = String(host ?? "").trim().toLowerCase();
|
|
if (!raw) return "";
|
|
|
|
if (raw.startsWith("[")) {
|
|
const end = raw.indexOf("]");
|
|
if (end !== -1) {
|
|
return raw.slice(1, end).trim();
|
|
}
|
|
}
|
|
|
|
const colonCount = (raw.match(/:/g) || []).length;
|
|
if (colonCount === 1) {
|
|
const idx = raw.lastIndexOf(":");
|
|
const maybePort = raw.slice(idx + 1);
|
|
if (/^\d+$/.test(maybePort)) {
|
|
raw = raw.slice(0, idx);
|
|
}
|
|
}
|
|
|
|
return raw;
|
|
};
|
|
|
|
const resolveHosts = (env = process.env) => {
|
|
const host = String(env.HOST ?? "").trim();
|
|
if (host) return [host];
|
|
return ["127.0.0.1", "::1"];
|
|
};
|
|
|
|
const resolveHost = (env = process.env) => {
|
|
const hosts = resolveHosts(env);
|
|
return hosts[0] ?? "127.0.0.1";
|
|
};
|
|
|
|
const isIpv4Loopback = (value) => value.startsWith("127.");
|
|
|
|
const isIpv6Loopback = (value) => {
|
|
if (value === "::1" || value === "0:0:0:0:0:0:0:1") return true;
|
|
if (!value.startsWith("::ffff:")) return false;
|
|
const mapped = value.slice("::ffff:".length);
|
|
return net.isIP(mapped) === 4 && isIpv4Loopback(mapped);
|
|
};
|
|
|
|
const isPublicHost = (host) => {
|
|
const normalized = normalizeHost(host);
|
|
if (!normalized) return false;
|
|
|
|
if (normalized === "localhost") return false;
|
|
if (normalized === "0.0.0.0" || normalized === "::") {
|
|
return true;
|
|
}
|
|
|
|
const ipVersion = net.isIP(normalized);
|
|
if (ipVersion === 4) {
|
|
return !isIpv4Loopback(normalized);
|
|
}
|
|
if (ipVersion === 6) {
|
|
return !isIpv6Loopback(normalized);
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
const assertPublicHostAllowed = ({ host, studioAccessToken }) => {
|
|
if (!isPublicHost(host)) return;
|
|
|
|
const token = String(studioAccessToken ?? "").trim();
|
|
if (token) return;
|
|
|
|
const normalized = normalizeHost(host) || String(host ?? "").trim() || "(unknown)";
|
|
throw new Error(
|
|
`Refusing to bind Studio to public host "${normalized}" without STUDIO_ACCESS_TOKEN. ` +
|
|
"Set STUDIO_ACCESS_TOKEN or bind HOST to 127.0.0.1/::1/localhost."
|
|
);
|
|
};
|
|
|
|
module.exports = {
|
|
resolveHosts,
|
|
resolveHost,
|
|
isPublicHost,
|
|
assertPublicHostAllowed,
|
|
};
|