diff --git a/src/middleware/core.js b/src/middleware/core.js index c836d4c..603617f 100644 --- a/src/middleware/core.js +++ b/src/middleware/core.js @@ -1,9 +1,11 @@ const http = require("http"); const fs = require("fs"); +const net = require("net"); const generateErrorStack = require("../utils/generateErrorStack.js"); const serverHTTPErrorDescs = require("../res/httpErrorDescriptions.js"); const fixNodeMojibakeURL = require("../utils/urlMojibakeFixer.js"); const getOS = require("../utils/getOS.js"); +const ipMatch = require("../utils/ipMatch.js"); const svrjsInfo = require("../../svrjs.json"); const version = svrjsInfo.version; @@ -295,15 +297,15 @@ module.exports = (req, res, logFacilities, config, next) => { "Host name rewritten: " + oldHostHeader + " => " + req.headers.host, ); - // Header and footer placeholders - res.head = ""; - res.foot = ""; + // Header and footer placeholders + res.head = ""; + res.foot = ""; - res.responseEnd = (body) => { - // If body is Buffer, then it is converted to String anyway. - res.write(head + body + foot); - res.end(); - } + res.responseEnd = (body) => { + // If body is Buffer, then it is converted to String anyway. + res.write(res.head + body + res.foot); + res.end(); + }; // Server error calling method res.error = (errorCode, extName, stack, ch) => { @@ -670,8 +672,16 @@ module.exports = (req, res, logFacilities, config, next) => { }; try { - res.head = fs.existsSync("./.head") ? 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 + res.head = fs.existsSync("./.head") + ? 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) { res.error(500, err); } diff --git a/src/middleware/redirects.js b/src/middleware/redirects.js index 53808b3..b65ff0b 100644 --- a/src/middleware/redirects.js +++ b/src/middleware/redirects.js @@ -3,7 +3,12 @@ module.exports = (req, res, logFacilities, config, next) => { let fromMain = !(config.secure && !req.socket.encrypted); // 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; if (hostx === undefined) { logFacilities.errmessage("Host header is missing."); @@ -17,7 +22,13 @@ module.exports = (req, res, logFacilities, config, next) => { 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; @@ -26,13 +37,21 @@ module.exports = (req, res, logFacilities, config, next) => { var hostPort = parsedHostx[2] ? parseInt(parsedHostx[2]) : 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; } else { destinationPort = config.spubport; } - redirect("https://" + hostname + (destinationPort == 443 ? "" : (":" + destinationPort)) + req.url); + res.redirect( + "https://" + + hostname + + (destinationPort == 443 ? "" : ":" + destinationPort) + + req.url, + ); return; } @@ -40,13 +59,23 @@ module.exports = (req, res, logFacilities, config, next) => { if (config.wwwredirect) { let hostname = req.headers.host.split(":"); 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(":"); - if (hostname == domain && hostname.indexOf("www.") != 0) { - res.redirect((req.socket.encrypted ? "https" : "http") + "://www." + hostname + (hostport ? ":" + hostport : "") + req.url.replace(/\/+/g, "/")); + if (hostname == config.domain && hostname.indexOf("www.") != 0) { + res.redirect( + (req.socket.encrypted ? "https" : "http") + + "://www." + + hostname + + (hostport ? ":" + hostport : "") + + req.url.replace(/\/+/g, "/"), + ); return; } } next(); -} \ No newline at end of file +}; diff --git a/src/middleware/urlSanitizer.js b/src/middleware/urlSanitizer.js index eddd133..fb41724 100644 --- a/src/middleware/urlSanitizer.js +++ b/src/middleware/urlSanitizer.js @@ -1,4 +1,3 @@ -const { emitWarning } = require("process"); const sanitizeURL = require("../utils/urlSanitizer.js"); const url = require("url"); diff --git a/src/middleware/webRootPostfixes.js b/src/middleware/webRootPostfixes.js index c8df4fa..d641177 100644 --- a/src/middleware/webRootPostfixes.js +++ b/src/middleware/webRootPostfixes.js @@ -1,116 +1,147 @@ +const url = require("url"); const createRegex = require("../utils/createRegex.js"); const ipMatch = require("../utils/ipMatch.js"); const sanitizeURL = require("../utils/urlSanitizer.js"); module.exports = (req, res, logFacilities, config, next) => { - const matchHostname = (hostname) => { - if (typeof hostname == "undefined" || hostname == "*") { - return true; - } else if ( - req.headers.host && - hostname.indexOf("*.") == 0 && - hostname != "*." - ) { - const hostnamesRoot = hostname.substring(2); - if ( - req.headers.host == hostnamesRoot || - (req.headers.host.length > hostnamesRoot.length && - req.headers.host.indexOf("." + hostnamesRoot) == - req.headers.host.length - hostnamesRoot.length - 1) - ) { - return true; - } - } else if (req.headers.host && req.headers.host == hostname) { - return true; - } + const matchHostname = (hostname) => { + if (typeof hostname == "undefined" || hostname == "*") { + return true; + } else if ( + req.headers.host && + hostname.indexOf("*.") == 0 && + hostname != "*." + ) { + const hostnamesRoot = hostname.substring(2); + if ( + req.headers.host == hostnamesRoot || + (req.headers.host.length > hostnamesRoot.length && + req.headers.host.indexOf("." + hostnamesRoot) == + req.headers.host.length - hostnamesRoot.length - 1) + ) { + return true; + } + } else if (req.headers.host && req.headers.host == hostname) { + return true; + } + return false; + }; + + // Add web root postfixes + if (!req.isProxy) { + let preparedReqUrl3 = config.allowPostfixDoubleSlashes + ? req.parsedURL.pathname.replace(/\/+/, "/") + + req.parsedURL.search + + req.parsedURL.hash + : req.url; + let urlWithPostfix = preparedReqUrl3; + let postfixPrefix = ""; + config.wwwrootPostfixPrefixesVHost.every(function (currentPostfixPrefix) { + if (preparedReqUrl3.indexOf(currentPostfixPrefix) == 0) { + if (currentPostfixPrefix.match(/\/+$/)) + postfixPrefix = currentPostfixPrefix.replace(/\/+$/, ""); + else if ( + urlWithPostfix.length == currentPostfixPrefix.length || + urlWithPostfix[currentPostfixPrefix.length] == "?" || + urlWithPostfix[currentPostfixPrefix.length] == "/" || + urlWithPostfix[currentPostfixPrefix.length] == "#" + ) + postfixPrefix = currentPostfixPrefix; + else return true; + urlWithPostfix = urlWithPostfix.substring(postfixPrefix.length); return false; - }; - - // Add web root postfixes - if (!req.isProxy) { - let preparedReqUrl3 = (config.allowPostfixDoubleSlashes ? (req.parsedURL.pathname.replace(/\/+/,"/") + req.parsedURL.search + req.parsedURL.hash) : req.url); - let urlWithPostfix = preparedReqUrl3; - let postfixPrefix = ""; - config.wwwrootPostfixPrefixesVHost.every(function (currentPostfixPrefix) { - if (preparedReqUrl3.indexOf(currentPostfixPrefix) == 0) { - if (currentPostfixPrefix.match(/\/+$/)) postfixPrefix = currentPostfixPrefix.replace(/\/+$/, ""); - else if (urlWithPostfix.length == currentPostfixPrefix.length || urlWithPostfix[currentPostfixPrefix.length] == "?" || urlWithPostfix[currentPostfixPrefix.length] == "/" || urlWithPostfix[currentPostfixPrefix.length] == "#") postfixPrefix = currentPostfixPrefix; - else return true; - urlWithPostfix = urlWithPostfix.substring(postfixPrefix.length); - return false; - } else { - return true; - } - }); - 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)))) { - urlWithPostfix = postfixPrefix + "/" + postfixEntry.postfix + urlWithPostfix; - return false; - } else { - return true; - } - }); - if (urlWithPostfix != preparedReqUrl3) { - logFacilities.resmessage("Added web root postfix: " + req.url + " => " + urlWithPostfix); - req.url = urlWithPostfix; - try { - req.parsedURL = new URL( - req.url, - "http" + - (req.socket.encrypted ? "s" : "") + - "://" + - (req.headers.host - ? req.headers.host - : config.domain - ? config.domain - : "unknown.invalid"), - ); - } catch (err) { - res.error(400, err); - return; - } - - let href = req.parsedURL.pathname + req.parsedURL.search; - - var sHref = sanitizeURL(href, allowDoubleSlashes); - var preparedReqUrl2 = req.parsedURL.pathname + req.parsedURL.search + req.parsedURL.hash; - - if (req.url != preparedReqUrl2 || sHref != href.replace(/\/\.(?=\/|$)/g, "/").replace(/\/+/g, "/")) { - res.error(403); - logFacilities.errmessage("Content blocked."); - return; - } else if (sHref != href) { - var rewrittenAgainURL = new url.Url(); - rewrittenAgainURL.path = null; - rewrittenAgainURL.href = null; - rewrittenAgainURL.pathname = sHref; - rewrittenAgainURL.hostname = null; - rewrittenAgainURL.host = null; - rewrittenAgainURL.port = null; - rewrittenAgainURL.protocol = null; - rewrittenAgainURL.slashes = null; - rewrittenAgainURL = url.format(rewrittenAgainURL); - logFacilities.resmessage("URL sanitized: " + req.url + " => " + rewrittenAgainURL); - req.url = rewrittenAgainURL; - try { - req.parsedURL = new URL( - req.url, - "http" + - (req.socket.encrypted ? "s" : "") + - "://" + - (req.headers.host - ? req.headers.host - : config.domain - ? config.domain - : "unknown.invalid"), - ); - } catch (err) { - res.error(400, err); - return; - } - } - } + } else { + return true; + } + }); + 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)) + ) + ) { + urlWithPostfix = + postfixPrefix + "/" + postfixEntry.postfix + urlWithPostfix; + return false; + } else { + return true; + } + }); + if (urlWithPostfix != preparedReqUrl3) { + logFacilities.resmessage( + "Added web root postfix: " + req.url + " => " + urlWithPostfix, + ); + req.url = urlWithPostfix; + try { + req.parsedURL = new URL( + req.url, + "http" + + (req.socket.encrypted ? "s" : "") + + "://" + + (req.headers.host + ? req.headers.host + : config.domain + ? config.domain + : "unknown.invalid"), + ); + } catch (err) { + res.error(400, err); + return; } - next(); -}; \ No newline at end of file + let href = req.parsedURL.pathname + req.parsedURL.search; + + var sHref = sanitizeURL(href, config.allowDoubleSlashes); + var preparedReqUrl2 = + req.parsedURL.pathname + req.parsedURL.search + req.parsedURL.hash; + + if ( + req.url != preparedReqUrl2 || + sHref != href.replace(/\/\.(?=\/|$)/g, "/").replace(/\/+/g, "/") + ) { + res.error(403); + logFacilities.errmessage("Content blocked."); + return; + } else if (sHref != href) { + var rewrittenAgainURL = new url.Url(); + rewrittenAgainURL.path = null; + rewrittenAgainURL.href = null; + rewrittenAgainURL.pathname = sHref; + rewrittenAgainURL.hostname = null; + rewrittenAgainURL.host = null; + rewrittenAgainURL.port = null; + rewrittenAgainURL.protocol = null; + rewrittenAgainURL.slashes = null; + rewrittenAgainURL = url.format(rewrittenAgainURL); + logFacilities.resmessage( + "URL sanitized: " + req.url + " => " + rewrittenAgainURL, + ); + req.url = rewrittenAgainURL; + try { + req.parsedURL = new URL( + req.url, + "http" + + (req.socket.encrypted ? "s" : "") + + "://" + + (req.headers.host + ? req.headers.host + : config.domain + ? config.domain + : "unknown.invalid"), + ); + } catch (err) { + res.error(400, err); + return; + } + } + } + } + + next(); +}; diff --git a/src/utils/createRegex.js b/src/utils/createRegex.js index 0a1c5a3..e5f81cc 100644 --- a/src/utils/createRegex.js +++ b/src/utils/createRegex.js @@ -1,12 +1,13 @@ const os = require("os"); function createRegex(regex, isPath) { - var regexStrMatch = regex.match(/^\/((?:\\.|[^\/\\])*)\/([a-zA-Z0-9]*)$/); - if (!regexStrMatch) throw new Error("Invalid regular expression: " + regex); - var searchString = regexStrMatch[1]; - var modifiers = regexStrMatch[2]; - if (isPath && !modifiers.match(/i/i) && os.platform() == "win32") modifiers += "i"; - return new RegExp(searchString, modifiers); - } + const regexStrMatch = regex.match(/^\/((?:\\.|[^\/\\])*)\/([a-zA-Z0-9]*)$/); + if (!regexStrMatch) throw new Error("Invalid regular expression: " + regex); + const searchString = regexStrMatch[1]; + let modifiers = regexStrMatch[2]; + if (isPath && !modifiers.match(/i/i) && os.platform() == "win32") + modifiers += "i"; + return new RegExp(searchString, modifiers); +} - module.exports = createRegex; \ No newline at end of file +module.exports = createRegex; diff --git a/src/utils/ipMatch.js b/src/utils/ipMatch.js index eab27e8..a5e2120 100644 --- a/src/utils/ipMatch.js +++ b/src/utils/ipMatch.js @@ -1,78 +1,82 @@ // Function to check if IPs are equal function ipMatch(IP1, IP2) { - if (!IP1) return true; - if (!IP2) return false; - - // Function to normalize IPv4 address (remove leading zeros) - function normalizeIPv4Address(address) { - return address.replace(/(^|\.)(?:0(?!\.|$))+/g, "$1"); - } - - // Function to expand IPv6 address to full format - function expandIPv6Address(address) { - var fullAddress = ""; - var expandedAddress = ""; - var validGroupCount = 8; - var validGroupSize = 4; - - var ipv4 = ""; - var extractIpv4 = /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/; - 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})/; - - if (validateIpv4.test(address)) { - var oldGroups = address.match(extractIpv4); - for (var i = 1; i < oldGroups.length; i++) { - ipv4 += ("00" + (parseInt(oldGroups[i], 10).toString(16))).slice(-2) + (i == 2 ? ":" : ""); - } - address = address.replace(extractIpv4, ipv4); - } - - if (address.indexOf("::") == -1) { - fullAddress = address; - } else { - var sides = address.split("::"); - var groupsPresent = 0; - sides.forEach(function (side) { - groupsPresent += side.split(":").length; - }); - fullAddress += sides[0] + ":"; - if (validGroupCount - groupsPresent > 1) { - fullAddress += "0000:".repeat(validGroupCount - groupsPresent); - } - fullAddress += sides[1]; - } - var groups = fullAddress.split(":"); - for (var i = 0; i < validGroupCount; i++) { - if (groups[i].length < validGroupSize) { - groups[i] = "0".repeat(validGroupSize - groups[i].length) + groups[i]; - } - expandedAddress += (i != validGroupCount - 1) ? groups[i] + ":" : groups[i]; - } - return expandedAddress; - } - - // Normalize or expand IP addresses - IP1 = IP1.toLowerCase(); - if (IP1 == "localhost") IP1 = "::1"; - if (IP1.indexOf("::ffff:") == 0) IP1 = IP1.substring(7); - if (IP1.indexOf(":") > -1) { - IP1 = expandIPv6Address(IP1); - } else { - IP1 = normalizeIPv4Address(IP1); - } - - IP2 = IP2.toLowerCase(); - if (IP2 == "localhost") IP2 = "::1"; - if (IP2.indexOf("::ffff:") == 0) IP2 = IP2.substring(7); - if (IP2.indexOf(":") > -1) { - IP2 = expandIPv6Address(IP2); - } else { - IP2 = normalizeIPv4Address(IP2); - } - - // Check if processed IPs are equal - if (IP1 == IP2) return true; - else return false; + if (!IP1) return true; + if (!IP2) return false; + + // Function to normalize IPv4 address (remove leading zeros) + function normalizeIPv4Address(address) { + return address.replace(/(^|\.)(?:0(?!\.|$))+/g, "$1"); } - module.exports = ipMatch; \ No newline at end of file + // Function to expand IPv6 address to full format + function expandIPv6Address(address) { + let fullAddress = ""; + let expandedAddress = ""; + let validGroupCount = 8; + let validGroupSize = 4; + + let ipv4 = ""; + const extractIpv4 = + /([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)) { + const oldGroups = address.match(extractIpv4); + for (let i = 1; i < oldGroups.length; i++) { + ipv4 += + ("00" + parseInt(oldGroups[i], 10).toString(16)).slice(-2) + + (i == 2 ? ":" : ""); + } + address = address.replace(extractIpv4, ipv4); + } + + if (address.indexOf("::") == -1) { + fullAddress = address; + } else { + const sides = address.split("::"); + let groupsPresent = 0; + sides.forEach((side) => { + groupsPresent += side.split(":").length; + }); + fullAddress += sides[0] + ":"; + if (validGroupCount - groupsPresent > 1) { + fullAddress += "0000:".repeat(validGroupCount - groupsPresent); + } + fullAddress += sides[1]; + } + let groups = fullAddress.split(":"); + for (let i = 0; i < validGroupCount; i++) { + if (groups[i].length < validGroupSize) { + groups[i] = "0".repeat(validGroupSize - groups[i].length) + groups[i]; + } + expandedAddress += i != validGroupCount - 1 ? groups[i] + ":" : groups[i]; + } + return expandedAddress; + } + + // Normalize or expand IP addresses + IP1 = IP1.toLowerCase(); + if (IP1 == "localhost") IP1 = "::1"; + if (IP1.indexOf("::ffff:") == 0) IP1 = IP1.substring(7); + if (IP1.indexOf(":") > -1) { + IP1 = expandIPv6Address(IP1); + } else { + IP1 = normalizeIPv4Address(IP1); + } + + IP2 = IP2.toLowerCase(); + if (IP2 == "localhost") IP2 = "::1"; + if (IP2.indexOf("::ffff:") == 0) IP2 = IP2.substring(7); + if (IP2.indexOf(":") > -1) { + IP2 = expandIPv6Address(IP2); + } else { + IP2 = normalizeIPv4Address(IP2); + } + + // Check if processed IPs are equal + if (IP1 == IP2) return true; + else return false; +} + +module.exports = ipMatch; diff --git a/tests/utils/createRegex.test.js b/tests/utils/createRegex.test.js index 39dd671..062e921 100644 --- a/tests/utils/createRegex.test.js +++ b/tests/utils/createRegex.test.js @@ -1,75 +1,77 @@ -const createRegex = require('../../src/utils/createRegex'); -const os = require('os'); +const createRegex = require("../../src/utils/createRegex"); +const os = require("os"); -jest.mock('os', () => ({ +jest.mock("os", () => ({ platform: jest.fn(), })); -describe('createRegex', () => { +describe("createRegex", () => { beforeEach(() => { os.platform.mockReset(); }); - test('should throw an error for invalid regular expression', () => { - expect(() => createRegex('invalid/regex', false)).toThrow('Invalid regular expression: invalid/regex'); + test("should throw an error for invalid regular expression", () => { + expect(() => createRegex("invalid/regex", false)).toThrow( + "Invalid regular expression: invalid/regex", + ); }); - test('should create a regular expression without modifiers', () => { - const regex = createRegex('/test/', false); + test("should create a regular expression without modifiers", () => { + const regex = createRegex("/test/", false); expect(regex).toBeInstanceOf(RegExp); - expect(regex.source).toBe('test'); - expect(regex.flags).toBe(''); + expect(regex.source).toBe("test"); + expect(regex.flags).toBe(""); }); - test('should create a regular expression with modifiers', () => { - const regex = createRegex('/test/gi', false); + test("should create a regular expression with modifiers", () => { + const regex = createRegex("/test/gi", false); expect(regex).toBeInstanceOf(RegExp); - expect(regex.source).toBe('test'); - expect(regex.flags).toBe('gi'); + expect(regex.source).toBe("test"); + expect(regex.flags).toBe("gi"); }); test('should add "i" modifier for paths on Windows', () => { - os.platform.mockReturnValue('win32'); - const regex = createRegex('/test/', true); + os.platform.mockReturnValue("win32"); + const regex = createRegex("/test/", true); expect(regex).toBeInstanceOf(RegExp); - expect(regex.source).toBe('test'); - expect(regex.flags).toBe('i'); + expect(regex.source).toBe("test"); + expect(regex.flags).toBe("i"); }); test('should not add "i" modifier for paths on non-Windows platforms', () => { - os.platform.mockReturnValue('linux'); - const regex = createRegex('/test/', true); + os.platform.mockReturnValue("linux"); + const regex = createRegex("/test/", true); expect(regex).toBeInstanceOf(RegExp); - expect(regex.source).toBe('test'); - expect(regex.flags).toBe(''); + expect(regex.source).toBe("test"); + expect(regex.flags).toBe(""); }); test('should not add "i" modifier if already present', () => { - os.platform.mockReturnValue('win32'); - const regex = createRegex('/test/i', true); + os.platform.mockReturnValue("win32"); + const regex = createRegex("/test/i", true); expect(regex).toBeInstanceOf(RegExp); - expect(regex.source).toBe('test'); - expect(regex.flags).toBe('i'); + expect(regex.source).toBe("test"); + expect(regex.flags).toBe("i"); }); - test('should handle escaped characters in the search string', () => { - const regex = createRegex('/test\\/path/', false); + test("should handle escaped characters in the search string", () => { + const regex = createRegex("/test\\/path/", false); expect(regex).toBeInstanceOf(RegExp); - expect(regex.source).toBe('test\\/path'); - expect(regex.flags).toBe(''); + expect(regex.source).toBe("test\\/path"); + expect(regex.flags).toBe(""); }); - test('should handle multiple modifiers', () => { - const regex = createRegex('/test/gim', false); + test("should handle multiple modifiers", () => { + const regex = createRegex("/test/gim", false); expect(regex).toBeInstanceOf(RegExp); - expect(regex.source).toBe('test'); - expect(regex.flags).toBe('gim'); + expect(regex.source).toBe("test"); + expect(regex.flags).toBe("gim"); }); - test('should handle empty search string', () => { - const regex = createRegex('/^$/', false); + test("should handle empty search string", () => { + const regex = createRegex("/^$/", false); expect(regex).toBeInstanceOf(RegExp); - expect(regex.source).toBe('^$'); - expect(regex.flags).toBe(''); + expect(regex.source).toBe("^$"); + expect(regex.flags).toBe(""); }); }); diff --git a/tests/utils/ipMatch.test.js b/tests/utils/ipMatch.test.js index 644793d..f7d317e 100644 --- a/tests/utils/ipMatch.test.js +++ b/tests/utils/ipMatch.test.js @@ -1,60 +1,82 @@ -const ipMatch = require('../../src/utils/ipMatch'); +const ipMatch = require("../../src/utils/ipMatch"); -describe('ipMatch', () => { - test('should return true if IP1 is empty', () => { - expect(ipMatch('', '192.168.1.1')).toBe(true); +describe("ipMatch", () => { + test("should return true if IP1 is empty", () => { + expect(ipMatch("", "192.168.1.1")).toBe(true); }); - test('should return false if IP2 is empty', () => { - expect(ipMatch('192.168.1.1', '')).toBe(false); + test("should return false if IP2 is empty", () => { + expect(ipMatch("192.168.1.1", "")).toBe(false); }); - test('should return true if both IPs are empty', () => { - expect(ipMatch('', '')).toBe(true); + test("should return true if both IPs are empty", () => { + expect(ipMatch("", "")).toBe(true); }); - test('should return true if both IPs are the same IPv4 address', () => { - expect(ipMatch('192.168.1.1', '192.168.1.1')).toBe(true); + test("should return true if both IPs are the same IPv4 address", () => { + expect(ipMatch("192.168.1.1", "192.168.1.1")).toBe(true); }); - test('should return false if IPs are different IPv4 addresses', () => { - expect(ipMatch('192.168.1.1', '192.168.1.2')).toBe(false); + test("should return false if IPs are different IPv4 addresses", () => { + expect(ipMatch("192.168.1.1", "192.168.1.2")).toBe(false); }); - test('should normalize IPv4 addresses with leading zeros', () => { - expect(ipMatch('192.168.001.001', '192.168.1.1')).toBe(true); + test("should normalize IPv4 addresses with leading zeros", () => { + expect(ipMatch("192.168.001.001", "192.168.1.1")).toBe(true); }); - 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); + 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); }); - 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); + 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); }); 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', () => { - expect(ipMatch('::ffff:192.168.1.1', '192.168.1.1')).toBe(true); + test("should handle IPv6 addresses with embedded IPv4 addresses", () => { + expect(ipMatch("::ffff:192.168.1.1", "192.168.1.1")).toBe(true); }); 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', () => { - 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); + test("should handle mixed case IP addresses", () => { + 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); }); - 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); + 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); }); - 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); + 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); }); });