@stuntman/server
Version:
Stuntman - HTTP proxy / mock server with API
83 lines • 3.06 kB
JavaScript
import { networkInterfaces } from 'os';
import dns, { Resolver as DNSResolver } from 'node:dns';
import { getDnsResolutionCache } from './storage.js';
import { errorToLog, logger } from '@stuntman/shared';
const localhostIPs = ['127.0.0.1', '::1'];
const IP_WITH_OPTIONAL_PORT_REGEX = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}(:[0-9]+)?$/i;
for (const nets of Object.values(networkInterfaces())) {
if (!nets) {
continue;
}
for (const net of nets) {
const familyV4Value = typeof net.family === 'string' ? 'IPv4' : 4;
if (net.family === familyV4Value && !localhostIPs.includes(net.address)) {
localhostIPs.push(net.address);
}
}
}
export class IPUtils {
dnsResolutionCache;
mockUuid;
externalDns = null;
constructor(options) {
this.mockUuid = options.mockUuid;
if (options.externalDns?.length) {
this.externalDns = new DNSResolver();
this.externalDns.setServers(options.externalDns);
}
this.dnsResolutionCache = getDnsResolutionCache(this.mockUuid);
}
isLocalhostIP(ip) {
return localhostIPs.includes(ip);
}
async resolveIPs(hostname, options) {
return new Promise((resolve, reject) => {
const callback = (error, addresses) => {
if (error) {
logger.debug({ error: errorToLog(error), hostname }, 'error resolving hostname');
reject(error);
return;
}
if (typeof addresses === 'string') {
logger.debug({ ip: [addresses], hostname }, 'resolved hostname');
resolve([addresses]);
return;
}
if (!addresses || addresses.length === 0) {
logger.debug({ hostname }, 'no addresses found');
resolve([]);
return;
}
logger.debug({ ip: addresses, hostname }, 'resolved hostname');
resolve(addresses);
};
if (options?.useExternalDns) {
if (!this.externalDns) {
reject(new Error('external dns servers not set'));
return;
}
this.externalDns.resolve(hostname, callback);
return;
}
// TODO general handling of IPv6
dns.resolve4(hostname, callback);
});
}
async resolveIP(hostname, options) {
const cachedIP = this.dnsResolutionCache.get(hostname);
if (cachedIP) {
return cachedIP;
}
const resolved = await this.resolveIPs(hostname, options);
if (!resolved || resolved.length < 1) {
throw new Error('unable to resolve IP');
}
const ip = resolved[0];
this.dnsResolutionCache.set(hostname, ip);
return ip;
}
isIP(hostname) {
return IP_WITH_OPTIONAL_PORT_REGEX.test(hostname);
}
}
//# sourceMappingURL=ipUtils.js.map