1
0
Fork 0
forked from svrjs/svrjs

Lint out the codebase.

This commit is contained in:
Dorian Niemiec 2024-08-24 08:07:31 +02:00
parent 1929641ba7
commit a49dba73fe
8 changed files with 374 additions and 276 deletions

View file

@ -1,9 +1,11 @@
const http = require("http"); const http = require("http");
const fs = require("fs"); const fs = require("fs");
const net = require("net");
const generateErrorStack = require("../utils/generateErrorStack.js"); const generateErrorStack = require("../utils/generateErrorStack.js");
const serverHTTPErrorDescs = require("../res/httpErrorDescriptions.js"); const serverHTTPErrorDescs = require("../res/httpErrorDescriptions.js");
const fixNodeMojibakeURL = require("../utils/urlMojibakeFixer.js"); const fixNodeMojibakeURL = require("../utils/urlMojibakeFixer.js");
const getOS = require("../utils/getOS.js"); const getOS = require("../utils/getOS.js");
const ipMatch = require("../utils/ipMatch.js");
const svrjsInfo = require("../../svrjs.json"); const svrjsInfo = require("../../svrjs.json");
const version = svrjsInfo.version; const version = svrjsInfo.version;
@ -301,9 +303,9 @@ module.exports = (req, res, logFacilities, config, next) => {
res.responseEnd = (body) => { res.responseEnd = (body) => {
// If body is Buffer, then it is converted to String anyway. // If body is Buffer, then it is converted to String anyway.
res.write(head + body + foot); res.write(res.head + body + res.foot);
res.end(); res.end();
} };
// Server error calling method // Server error calling method
res.error = (errorCode, extName, stack, ch) => { res.error = (errorCode, extName, stack, ch) => {
@ -670,8 +672,16 @@ module.exports = (req, res, logFacilities, config, next) => {
}; };
try { try {
res.head = fs.existsSync("./.head") ? fs.readFileSync("./.head").toString() : (fs.existsSync("./head.html") ? fs.readFileSync("./head.html").toString() : ""); // header res.head = fs.existsSync("./.head")
res.foot = fs.existsSync("./.foot") ? fs.readFileSync("./.foot").toString() : (fs.existsSync("./foot.html") ? fs.readFileSync("./foot.html").toString() : ""); // footer ? fs.readFileSync("./.head").toString()
: fs.existsSync("./head.html")
? fs.readFileSync("./head.html").toString()
: ""; // header
res.foot = fs.existsSync("./.foot")
? fs.readFileSync("./.foot").toString()
: fs.existsSync("./foot.html")
? fs.readFileSync("./foot.html").toString()
: ""; // footer
} catch (err) { } catch (err) {
res.error(500, err); res.error(500, err);
} }

View file

@ -3,7 +3,12 @@ module.exports = (req, res, logFacilities, config, next) => {
let fromMain = !(config.secure && !req.socket.encrypted); let fromMain = !(config.secure && !req.socket.encrypted);
// Handle redirects to HTTPS // Handle redirects to HTTPS
if (config.secure && !fromMain && !config.disableNonEncryptedServer && !config.disableToHTTPSRedirect) { if (
config.secure &&
!fromMain &&
!config.disableNonEncryptedServer &&
!config.disableToHTTPSRedirect
) {
var hostx = req.headers.host; var hostx = req.headers.host;
if (hostx === undefined) { if (hostx === undefined) {
logFacilities.errmessage("Host header is missing."); logFacilities.errmessage("Host header is missing.");
@ -17,7 +22,13 @@ module.exports = (req, res, logFacilities, config, next) => {
return; return;
} }
var isPublicServer = !(req.socket.realRemoteAddress ? req.socket.realRemoteAddress : req.socket.remoteAddress).match(/^(?:localhost$|::1$|f[c-d][0-9a-f]{2}:|(?:::ffff:)?(?:(?:127|10)\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|192\.168\.[0-9]{1,3}\.[0-9]{1,3}|172\.(?:1[6-9]|2[0-9]|3[0-1])\.[0-9]{1,3}\.[0-9]{1,3})$)/i); var isPublicServer = !(
req.socket.realRemoteAddress
? req.socket.realRemoteAddress
: req.socket.remoteAddress
).match(
/^(?:localhost$|::1$|f[c-d][0-9a-f]{2}:|(?:::ffff:)?(?:(?:127|10)\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|192\.168\.[0-9]{1,3}\.[0-9]{1,3}|172\.(?:1[6-9]|2[0-9]|3[0-1])\.[0-9]{1,3}\.[0-9]{1,3})$)/i,
);
var destinationPort = 0; var destinationPort = 0;
@ -26,13 +37,21 @@ module.exports = (req, res, logFacilities, config, next) => {
var hostPort = parsedHostx[2] ? parseInt(parsedHostx[2]) : 80; var hostPort = parsedHostx[2] ? parseInt(parsedHostx[2]) : 80;
if (isNaN(hostPort)) hostPort = 80; if (isNaN(hostPort)) hostPort = 80;
if (hostPort == config.port || (config.port == config.pubport && !isPublicServer)) { if (
hostPort == config.port ||
(config.port == config.pubport && !isPublicServer)
) {
destinationPort = config.sport; destinationPort = config.sport;
} else { } else {
destinationPort = config.spubport; destinationPort = config.spubport;
} }
redirect("https://" + hostname + (destinationPort == 443 ? "" : (":" + destinationPort)) + req.url); res.redirect(
"https://" +
hostname +
(destinationPort == 443 ? "" : ":" + destinationPort) +
req.url,
);
return; return;
} }
@ -40,13 +59,23 @@ module.exports = (req, res, logFacilities, config, next) => {
if (config.wwwredirect) { if (config.wwwredirect) {
let hostname = req.headers.host.split(":"); let hostname = req.headers.host.split(":");
let hostport = null; let hostport = null;
if (hostname.length > 1 && (hostname[0] != "[" || hostname[hostname.length - 1] != "]")) hostport = hostname.pop(); if (
hostname.length > 1 &&
(hostname[0] != "[" || hostname[hostname.length - 1] != "]")
)
hostport = hostname.pop();
hostname = hostname.join(":"); hostname = hostname.join(":");
if (hostname == domain && hostname.indexOf("www.") != 0) { if (hostname == config.domain && hostname.indexOf("www.") != 0) {
res.redirect((req.socket.encrypted ? "https" : "http") + "://www." + hostname + (hostport ? ":" + hostport : "") + req.url.replace(/\/+/g, "/")); res.redirect(
(req.socket.encrypted ? "https" : "http") +
"://www." +
hostname +
(hostport ? ":" + hostport : "") +
req.url.replace(/\/+/g, "/"),
);
return; return;
} }
} }
next(); next();
} };

View file

@ -1,4 +1,3 @@
const { emitWarning } = require("process");
const sanitizeURL = require("../utils/urlSanitizer.js"); const sanitizeURL = require("../utils/urlSanitizer.js");
const url = require("url"); const url = require("url");

View file

@ -1,3 +1,4 @@
const url = require("url");
const createRegex = require("../utils/createRegex.js"); const createRegex = require("../utils/createRegex.js");
const ipMatch = require("../utils/ipMatch.js"); const ipMatch = require("../utils/ipMatch.js");
const sanitizeURL = require("../utils/urlSanitizer.js"); const sanitizeURL = require("../utils/urlSanitizer.js");
@ -28,13 +29,24 @@ module.exports = (req, res, logFacilities, config, next) => {
// Add web root postfixes // Add web root postfixes
if (!req.isProxy) { if (!req.isProxy) {
let preparedReqUrl3 = (config.allowPostfixDoubleSlashes ? (req.parsedURL.pathname.replace(/\/+/,"/") + req.parsedURL.search + req.parsedURL.hash) : req.url); let preparedReqUrl3 = config.allowPostfixDoubleSlashes
? req.parsedURL.pathname.replace(/\/+/, "/") +
req.parsedURL.search +
req.parsedURL.hash
: req.url;
let urlWithPostfix = preparedReqUrl3; let urlWithPostfix = preparedReqUrl3;
let postfixPrefix = ""; let postfixPrefix = "";
config.wwwrootPostfixPrefixesVHost.every(function (currentPostfixPrefix) { config.wwwrootPostfixPrefixesVHost.every(function (currentPostfixPrefix) {
if (preparedReqUrl3.indexOf(currentPostfixPrefix) == 0) { if (preparedReqUrl3.indexOf(currentPostfixPrefix) == 0) {
if (currentPostfixPrefix.match(/\/+$/)) postfixPrefix = currentPostfixPrefix.replace(/\/+$/, ""); if (currentPostfixPrefix.match(/\/+$/))
else if (urlWithPostfix.length == currentPostfixPrefix.length || urlWithPostfix[currentPostfixPrefix.length] == "?" || urlWithPostfix[currentPostfixPrefix.length] == "/" || urlWithPostfix[currentPostfixPrefix.length] == "#") postfixPrefix = currentPostfixPrefix; postfixPrefix = currentPostfixPrefix.replace(/\/+$/, "");
else if (
urlWithPostfix.length == currentPostfixPrefix.length ||
urlWithPostfix[currentPostfixPrefix.length] == "?" ||
urlWithPostfix[currentPostfixPrefix.length] == "/" ||
urlWithPostfix[currentPostfixPrefix.length] == "#"
)
postfixPrefix = currentPostfixPrefix;
else return true; else return true;
urlWithPostfix = urlWithPostfix.substring(postfixPrefix.length); urlWithPostfix = urlWithPostfix.substring(postfixPrefix.length);
return false; return false;
@ -43,15 +55,28 @@ module.exports = (req, res, logFacilities, config, next) => {
} }
}); });
config.wwwrootPostfixesVHost.every(function (postfixEntry) { config.wwwrootPostfixesVHost.every(function (postfixEntry) {
if (matchHostname(postfixEntry.host) && ipMatch(postfixEntry.ip, req.socket ? req.socket.localAddress : undefined) && !(postfixEntry.skipRegex && preparedReqUrl3.match(createRegex(postfixEntry.skipRegex)))) { if (
urlWithPostfix = postfixPrefix + "/" + postfixEntry.postfix + urlWithPostfix; matchHostname(postfixEntry.host) &&
ipMatch(
postfixEntry.ip,
req.socket ? req.socket.localAddress : undefined,
) &&
!(
postfixEntry.skipRegex &&
preparedReqUrl3.match(createRegex(postfixEntry.skipRegex))
)
) {
urlWithPostfix =
postfixPrefix + "/" + postfixEntry.postfix + urlWithPostfix;
return false; return false;
} else { } else {
return true; return true;
} }
}); });
if (urlWithPostfix != preparedReqUrl3) { if (urlWithPostfix != preparedReqUrl3) {
logFacilities.resmessage("Added web root postfix: " + req.url + " => " + urlWithPostfix); logFacilities.resmessage(
"Added web root postfix: " + req.url + " => " + urlWithPostfix,
);
req.url = urlWithPostfix; req.url = urlWithPostfix;
try { try {
req.parsedURL = new URL( req.parsedURL = new URL(
@ -72,10 +97,14 @@ module.exports = (req, res, logFacilities, config, next) => {
let href = req.parsedURL.pathname + req.parsedURL.search; let href = req.parsedURL.pathname + req.parsedURL.search;
var sHref = sanitizeURL(href, allowDoubleSlashes); var sHref = sanitizeURL(href, config.allowDoubleSlashes);
var preparedReqUrl2 = req.parsedURL.pathname + req.parsedURL.search + req.parsedURL.hash; var preparedReqUrl2 =
req.parsedURL.pathname + req.parsedURL.search + req.parsedURL.hash;
if (req.url != preparedReqUrl2 || sHref != href.replace(/\/\.(?=\/|$)/g, "/").replace(/\/+/g, "/")) { if (
req.url != preparedReqUrl2 ||
sHref != href.replace(/\/\.(?=\/|$)/g, "/").replace(/\/+/g, "/")
) {
res.error(403); res.error(403);
logFacilities.errmessage("Content blocked."); logFacilities.errmessage("Content blocked.");
return; return;
@ -90,7 +119,9 @@ module.exports = (req, res, logFacilities, config, next) => {
rewrittenAgainURL.protocol = null; rewrittenAgainURL.protocol = null;
rewrittenAgainURL.slashes = null; rewrittenAgainURL.slashes = null;
rewrittenAgainURL = url.format(rewrittenAgainURL); rewrittenAgainURL = url.format(rewrittenAgainURL);
logFacilities.resmessage("URL sanitized: " + req.url + " => " + rewrittenAgainURL); logFacilities.resmessage(
"URL sanitized: " + req.url + " => " + rewrittenAgainURL,
);
req.url = rewrittenAgainURL; req.url = rewrittenAgainURL;
try { try {
req.parsedURL = new URL( req.parsedURL = new URL(

View file

@ -1,11 +1,12 @@
const os = require("os"); const os = require("os");
function createRegex(regex, isPath) { function createRegex(regex, isPath) {
var regexStrMatch = regex.match(/^\/((?:\\.|[^\/\\])*)\/([a-zA-Z0-9]*)$/); const regexStrMatch = regex.match(/^\/((?:\\.|[^\/\\])*)\/([a-zA-Z0-9]*)$/);
if (!regexStrMatch) throw new Error("Invalid regular expression: " + regex); if (!regexStrMatch) throw new Error("Invalid regular expression: " + regex);
var searchString = regexStrMatch[1]; const searchString = regexStrMatch[1];
var modifiers = regexStrMatch[2]; let modifiers = regexStrMatch[2];
if (isPath && !modifiers.match(/i/i) && os.platform() == "win32") modifiers += "i"; if (isPath && !modifiers.match(/i/i) && os.platform() == "win32")
modifiers += "i";
return new RegExp(searchString, modifiers); return new RegExp(searchString, modifiers);
} }

View file

@ -10,19 +10,23 @@ function ipMatch(IP1, IP2) {
// Function to expand IPv6 address to full format // Function to expand IPv6 address to full format
function expandIPv6Address(address) { function expandIPv6Address(address) {
var fullAddress = ""; let fullAddress = "";
var expandedAddress = ""; let expandedAddress = "";
var validGroupCount = 8; let validGroupCount = 8;
var validGroupSize = 4; let validGroupSize = 4;
var ipv4 = ""; let ipv4 = "";
var extractIpv4 = /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/; const extractIpv4 =
var validateIpv4 = /((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})/; /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/;
const validateIpv4 =
/((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})/;
if (validateIpv4.test(address)) { if (validateIpv4.test(address)) {
var oldGroups = address.match(extractIpv4); const oldGroups = address.match(extractIpv4);
for (var i = 1; i < oldGroups.length; i++) { for (let i = 1; i < oldGroups.length; i++) {
ipv4 += ("00" + (parseInt(oldGroups[i], 10).toString(16))).slice(-2) + (i == 2 ? ":" : ""); ipv4 +=
("00" + parseInt(oldGroups[i], 10).toString(16)).slice(-2) +
(i == 2 ? ":" : "");
} }
address = address.replace(extractIpv4, ipv4); address = address.replace(extractIpv4, ipv4);
} }
@ -30,9 +34,9 @@ function ipMatch(IP1, IP2) {
if (address.indexOf("::") == -1) { if (address.indexOf("::") == -1) {
fullAddress = address; fullAddress = address;
} else { } else {
var sides = address.split("::"); const sides = address.split("::");
var groupsPresent = 0; let groupsPresent = 0;
sides.forEach(function (side) { sides.forEach((side) => {
groupsPresent += side.split(":").length; groupsPresent += side.split(":").length;
}); });
fullAddress += sides[0] + ":"; fullAddress += sides[0] + ":";
@ -41,12 +45,12 @@ function ipMatch(IP1, IP2) {
} }
fullAddress += sides[1]; fullAddress += sides[1];
} }
var groups = fullAddress.split(":"); let groups = fullAddress.split(":");
for (var i = 0; i < validGroupCount; i++) { for (let i = 0; i < validGroupCount; i++) {
if (groups[i].length < validGroupSize) { if (groups[i].length < validGroupSize) {
groups[i] = "0".repeat(validGroupSize - groups[i].length) + groups[i]; groups[i] = "0".repeat(validGroupSize - groups[i].length) + groups[i];
} }
expandedAddress += (i != validGroupCount - 1) ? groups[i] + ":" : groups[i]; expandedAddress += i != validGroupCount - 1 ? groups[i] + ":" : groups[i];
} }
return expandedAddress; return expandedAddress;
} }

View file

@ -1,75 +1,77 @@
const createRegex = require('../../src/utils/createRegex'); const createRegex = require("../../src/utils/createRegex");
const os = require('os'); const os = require("os");
jest.mock('os', () => ({ jest.mock("os", () => ({
platform: jest.fn(), platform: jest.fn(),
})); }));
describe('createRegex', () => { describe("createRegex", () => {
beforeEach(() => { beforeEach(() => {
os.platform.mockReset(); os.platform.mockReset();
}); });
test('should throw an error for invalid regular expression', () => { test("should throw an error for invalid regular expression", () => {
expect(() => createRegex('invalid/regex', false)).toThrow('Invalid regular expression: invalid/regex'); expect(() => createRegex("invalid/regex", false)).toThrow(
"Invalid regular expression: invalid/regex",
);
}); });
test('should create a regular expression without modifiers', () => { test("should create a regular expression without modifiers", () => {
const regex = createRegex('/test/', false); const regex = createRegex("/test/", false);
expect(regex).toBeInstanceOf(RegExp); expect(regex).toBeInstanceOf(RegExp);
expect(regex.source).toBe('test'); expect(regex.source).toBe("test");
expect(regex.flags).toBe(''); expect(regex.flags).toBe("");
}); });
test('should create a regular expression with modifiers', () => { test("should create a regular expression with modifiers", () => {
const regex = createRegex('/test/gi', false); const regex = createRegex("/test/gi", false);
expect(regex).toBeInstanceOf(RegExp); expect(regex).toBeInstanceOf(RegExp);
expect(regex.source).toBe('test'); expect(regex.source).toBe("test");
expect(regex.flags).toBe('gi'); expect(regex.flags).toBe("gi");
}); });
test('should add "i" modifier for paths on Windows', () => { test('should add "i" modifier for paths on Windows', () => {
os.platform.mockReturnValue('win32'); os.platform.mockReturnValue("win32");
const regex = createRegex('/test/', true); const regex = createRegex("/test/", true);
expect(regex).toBeInstanceOf(RegExp); expect(regex).toBeInstanceOf(RegExp);
expect(regex.source).toBe('test'); expect(regex.source).toBe("test");
expect(regex.flags).toBe('i'); expect(regex.flags).toBe("i");
}); });
test('should not add "i" modifier for paths on non-Windows platforms', () => { test('should not add "i" modifier for paths on non-Windows platforms', () => {
os.platform.mockReturnValue('linux'); os.platform.mockReturnValue("linux");
const regex = createRegex('/test/', true); const regex = createRegex("/test/", true);
expect(regex).toBeInstanceOf(RegExp); expect(regex).toBeInstanceOf(RegExp);
expect(regex.source).toBe('test'); expect(regex.source).toBe("test");
expect(regex.flags).toBe(''); expect(regex.flags).toBe("");
}); });
test('should not add "i" modifier if already present', () => { test('should not add "i" modifier if already present', () => {
os.platform.mockReturnValue('win32'); os.platform.mockReturnValue("win32");
const regex = createRegex('/test/i', true); const regex = createRegex("/test/i", true);
expect(regex).toBeInstanceOf(RegExp); expect(regex).toBeInstanceOf(RegExp);
expect(regex.source).toBe('test'); expect(regex.source).toBe("test");
expect(regex.flags).toBe('i'); expect(regex.flags).toBe("i");
}); });
test('should handle escaped characters in the search string', () => { test("should handle escaped characters in the search string", () => {
const regex = createRegex('/test\\/path/', false); const regex = createRegex("/test\\/path/", false);
expect(regex).toBeInstanceOf(RegExp); expect(regex).toBeInstanceOf(RegExp);
expect(regex.source).toBe('test\\/path'); expect(regex.source).toBe("test\\/path");
expect(regex.flags).toBe(''); expect(regex.flags).toBe("");
}); });
test('should handle multiple modifiers', () => { test("should handle multiple modifiers", () => {
const regex = createRegex('/test/gim', false); const regex = createRegex("/test/gim", false);
expect(regex).toBeInstanceOf(RegExp); expect(regex).toBeInstanceOf(RegExp);
expect(regex.source).toBe('test'); expect(regex.source).toBe("test");
expect(regex.flags).toBe('gim'); expect(regex.flags).toBe("gim");
}); });
test('should handle empty search string', () => { test("should handle empty search string", () => {
const regex = createRegex('/^$/', false); const regex = createRegex("/^$/", false);
expect(regex).toBeInstanceOf(RegExp); expect(regex).toBeInstanceOf(RegExp);
expect(regex.source).toBe('^$'); expect(regex.source).toBe("^$");
expect(regex.flags).toBe(''); expect(regex.flags).toBe("");
}); });
}); });

View file

@ -1,60 +1,82 @@
const ipMatch = require('../../src/utils/ipMatch'); const ipMatch = require("../../src/utils/ipMatch");
describe('ipMatch', () => { describe("ipMatch", () => {
test('should return true if IP1 is empty', () => { test("should return true if IP1 is empty", () => {
expect(ipMatch('', '192.168.1.1')).toBe(true); expect(ipMatch("", "192.168.1.1")).toBe(true);
}); });
test('should return false if IP2 is empty', () => { test("should return false if IP2 is empty", () => {
expect(ipMatch('192.168.1.1', '')).toBe(false); expect(ipMatch("192.168.1.1", "")).toBe(false);
}); });
test('should return true if both IPs are empty', () => { test("should return true if both IPs are empty", () => {
expect(ipMatch('', '')).toBe(true); expect(ipMatch("", "")).toBe(true);
}); });
test('should return true if both IPs are the same IPv4 address', () => { test("should return true if both IPs are the same IPv4 address", () => {
expect(ipMatch('192.168.1.1', '192.168.1.1')).toBe(true); expect(ipMatch("192.168.1.1", "192.168.1.1")).toBe(true);
}); });
test('should return false if IPs are different IPv4 addresses', () => { test("should return false if IPs are different IPv4 addresses", () => {
expect(ipMatch('192.168.1.1', '192.168.1.2')).toBe(false); expect(ipMatch("192.168.1.1", "192.168.1.2")).toBe(false);
}); });
test('should normalize IPv4 addresses with leading zeros', () => { test("should normalize IPv4 addresses with leading zeros", () => {
expect(ipMatch('192.168.001.001', '192.168.1.1')).toBe(true); expect(ipMatch("192.168.001.001", "192.168.1.1")).toBe(true);
}); });
test('should return true if both IPs are the same IPv6 address', () => { test("should return true if both IPs are the same IPv6 address", () => {
expect(ipMatch('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:db8:85a3::8a2e:370:7334')).toBe(true); expect(
ipMatch(
"2001:0db8:85a3:0000:0000:8a2e:0370:7334",
"2001:db8:85a3::8a2e:370:7334",
),
).toBe(true);
}); });
test('should return false if IPs are different IPv6 addresses', () => { test("should return false if IPs are different IPv6 addresses", () => {
expect(ipMatch('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:db8:85a3::8a2e:370:7335')).toBe(false); expect(
ipMatch(
"2001:0db8:85a3:0000:0000:8a2e:0370:7334",
"2001:db8:85a3::8a2e:370:7335",
),
).toBe(false);
}); });
test('should expand IPv6 addresses with "::"', () => { test('should expand IPv6 addresses with "::"', () => {
expect(ipMatch('::1', '0:0:0:0:0:0:0:1')).toBe(true); expect(ipMatch("::1", "0:0:0:0:0:0:0:1")).toBe(true);
}); });
test('should handle IPv6 addresses with embedded IPv4 addresses', () => { test("should handle IPv6 addresses with embedded IPv4 addresses", () => {
expect(ipMatch('::ffff:192.168.1.1', '192.168.1.1')).toBe(true); expect(ipMatch("::ffff:192.168.1.1", "192.168.1.1")).toBe(true);
}); });
test('should handle "localhost" as IPv6 loopback address', () => { test('should handle "localhost" as IPv6 loopback address', () => {
expect(ipMatch('localhost', '::1')).toBe(true); expect(ipMatch("localhost", "::1")).toBe(true);
}); });
test('should handle mixed case IP addresses', () => { test("should handle mixed case IP addresses", () => {
expect(ipMatch('192.168.1.1', '192.168.1.1')).toBe(true); expect(ipMatch("192.168.1.1", "192.168.1.1")).toBe(true);
expect(ipMatch('2001:DB8:85A3::8A2E:370:7334', '2001:db8:85a3::8a2e:370:7334')).toBe(true); expect(
ipMatch("2001:DB8:85A3::8A2E:370:7334", "2001:db8:85a3::8a2e:370:7334"),
).toBe(true);
}); });
test('should handle IPv6 addresses with leading zeros', () => { test("should handle IPv6 addresses with leading zeros", () => {
expect(ipMatch('2001:0db8:85a3:0000:0000:8a2e:0370:7334', '2001:db8:85a3::8a2e:370:7334')).toBe(true); expect(
ipMatch(
"2001:0db8:85a3:0000:0000:8a2e:0370:7334",
"2001:db8:85a3::8a2e:370:7334",
),
).toBe(true);
}); });
test('should handle IPv6 addresses with mixed case and leading zeros', () => { test("should handle IPv6 addresses with mixed case and leading zeros", () => {
expect(ipMatch('2001:0DB8:85A3:0000:0000:8A2E:0370:7334', '2001:db8:85a3::8a2e:370:7334')).toBe(true); expect(
ipMatch(
"2001:0DB8:85A3:0000:0000:8A2E:0370:7334",
"2001:db8:85a3::8a2e:370:7334",
),
).toBe(true);
}); });
}); });