@tinyhttp/proxy-addr
Advanced tools
Comparing version 2.0.4 to 2.0.5
@@ -1,190 +0,135 @@ | ||
import { forwarded } from '@tinyhttp/forwarded'; | ||
import ipaddr from 'ipaddr.js'; | ||
import { forwarded } from "@tinyhttp/forwarded"; | ||
import ipaddr from "ipaddr.js"; | ||
const DIGIT_REGEXP = /^[0-9]+$/; | ||
const isip = ipaddr.isValid; | ||
const parseip = ipaddr.parse; | ||
/** | ||
* Pre-defined IP ranges. | ||
*/ | ||
const IP_RANGES = { | ||
linklocal: ['169.254.0.0/16', 'fe80::/10'], | ||
loopback: ['127.0.0.1/8', '::1/128'], | ||
uniquelocal: ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', 'fc00::/7'] | ||
linklocal: ["169.254.0.0/16", "fe80::/10"], | ||
loopback: ["127.0.0.1/8", "::1/128"], | ||
uniquelocal: ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "fc00::/7"] | ||
}; | ||
/** | ||
* Get all addresses in the request, optionally stopping | ||
* at the first untrusted. | ||
* | ||
* @param request | ||
* @param trust | ||
*/ | ||
function alladdrs(req, trust) { | ||
// get addresses | ||
const addrs = forwarded(req); | ||
if (!trust) | ||
return addrs; | ||
if (typeof trust !== 'function') | ||
trust = compile(trust); | ||
for (let i = 0; i < addrs.length - 1; i++) { | ||
if (trust(addrs[i], i)) | ||
continue; | ||
addrs.length = i + 1; | ||
} | ||
const addrs = forwarded(req); | ||
if (!trust) | ||
return addrs; | ||
if (typeof trust !== "function") | ||
trust = compile(trust); | ||
for (let i = 0; i < addrs.length - 1; i++) { | ||
if (trust(addrs[i], i)) | ||
continue; | ||
addrs.length = i + 1; | ||
} | ||
return addrs; | ||
} | ||
/** | ||
* Compile argument into trust function. | ||
* | ||
* @param val | ||
*/ | ||
function compile(val) { | ||
let trust; | ||
if (typeof val === 'string') | ||
trust = [val]; | ||
else if (Array.isArray(val)) | ||
trust = val.slice(); | ||
else | ||
throw new TypeError('unsupported trust argument'); | ||
for (let i = 0; i < trust.length; i++) { | ||
val = trust[i]; | ||
if (!Object.prototype.hasOwnProperty.call(IP_RANGES, val)) | ||
continue; | ||
// Splice in pre-defined range | ||
val = IP_RANGES[val]; | ||
// eslint-disable-next-line prefer-spread | ||
trust.splice.apply(trust, [i, 1].concat(val)); | ||
i += val.length - 1; | ||
} | ||
return compileTrust(compileRangeSubnets(trust)); | ||
let trust; | ||
if (typeof val === "string") | ||
trust = [val]; | ||
else if (Array.isArray(val)) | ||
trust = val.slice(); | ||
else | ||
throw new TypeError("unsupported trust argument"); | ||
for (let i = 0; i < trust.length; i++) { | ||
val = trust[i]; | ||
if (!Object.prototype.hasOwnProperty.call(IP_RANGES, val)) | ||
continue; | ||
val = IP_RANGES[val]; | ||
trust.splice.apply(trust, [i, 1].concat(val)); | ||
i += val.length - 1; | ||
} | ||
return compileTrust(compileRangeSubnets(trust)); | ||
} | ||
/** | ||
* Compile `arr` elements into range subnets. | ||
*/ | ||
function compileRangeSubnets(arr) { | ||
const rangeSubnets = new Array(arr.length); | ||
for (let i = 0; i < arr.length; i++) | ||
rangeSubnets[i] = parseIPNotation(arr[i]); | ||
return rangeSubnets; | ||
const rangeSubnets = new Array(arr.length); | ||
for (let i = 0; i < arr.length; i++) | ||
rangeSubnets[i] = parseIPNotation(arr[i]); | ||
return rangeSubnets; | ||
} | ||
/** | ||
* Compile range subnet array into trust function. | ||
* | ||
* @param rangeSubnets | ||
*/ | ||
function compileTrust(rangeSubnets) { | ||
// Return optimized function based on length | ||
const len = rangeSubnets.length; | ||
return len === 0 ? trustNone : len === 1 ? trustSingle(rangeSubnets[0]) : trustMulti(rangeSubnets); | ||
const len = rangeSubnets.length; | ||
return len === 0 ? trustNone : len === 1 ? trustSingle(rangeSubnets[0]) : trustMulti(rangeSubnets); | ||
} | ||
/** | ||
* Parse IP notation string into range subnet. | ||
* | ||
* @param {String} note | ||
* @private | ||
*/ | ||
function parseIPNotation(note) { | ||
const pos = note.lastIndexOf('/'); | ||
const str = pos !== -1 ? note.substring(0, pos) : note; | ||
if (!isip(str)) | ||
throw new TypeError('invalid IP address: ' + str); | ||
let ip = parseip(str); | ||
if (pos === -1 && ip.kind() === 'ipv6') { | ||
ip = ip; | ||
if (ip.isIPv4MappedAddress()) | ||
ip = ip.toIPv4Address(); | ||
} | ||
const max = ip.kind() === 'ipv6' ? 128 : 32; | ||
let range = pos !== -1 ? note.substring(pos + 1, note.length) : null; | ||
if (range === null) | ||
range = max; | ||
else if (DIGIT_REGEXP.test(range)) | ||
range = parseInt(range, 10); | ||
else if (ip.kind() === 'ipv4' && isip(range)) | ||
range = parseNetmask(range); | ||
else | ||
range = null; | ||
if (range <= 0 || range > max) | ||
throw new TypeError('invalid range on address: ' + note); | ||
return [ip, range]; | ||
const pos = note.lastIndexOf("/"); | ||
const str = pos !== -1 ? note.substring(0, pos) : note; | ||
if (!isip(str)) | ||
throw new TypeError("invalid IP address: " + str); | ||
let ip = parseip(str); | ||
if (pos === -1 && ip.kind() === "ipv6") { | ||
ip = ip; | ||
if (ip.isIPv4MappedAddress()) | ||
ip = ip.toIPv4Address(); | ||
} | ||
const max = ip.kind() === "ipv6" ? 128 : 32; | ||
let range = pos !== -1 ? note.substring(pos + 1, note.length) : null; | ||
if (range === null) | ||
range = max; | ||
else if (DIGIT_REGEXP.test(range)) | ||
range = parseInt(range, 10); | ||
else if (ip.kind() === "ipv4" && isip(range)) | ||
range = parseNetmask(range); | ||
else | ||
range = null; | ||
if (range <= 0 || range > max) | ||
throw new TypeError("invalid range on address: " + note); | ||
return [ip, range]; | ||
} | ||
/** | ||
* Parse netmask string into CIDR range. | ||
* | ||
* @param netmask | ||
* @private | ||
*/ | ||
function parseNetmask(netmask) { | ||
const ip = parseip(netmask); | ||
return ip.kind() === 'ipv4' ? ip.prefixLengthFromSubnetMask() : null; | ||
const ip = parseip(netmask); | ||
return ip.kind() === "ipv4" ? ip.prefixLengthFromSubnetMask() : null; | ||
} | ||
/** | ||
* Determine address of proxied request. | ||
* | ||
* @param request | ||
* @param trust | ||
* @public | ||
*/ | ||
function proxyaddr(req, trust) { | ||
const addrs = alladdrs(req, trust); | ||
return addrs[addrs.length - 1]; | ||
const addrs = alladdrs(req, trust); | ||
return addrs[addrs.length - 1]; | ||
} | ||
/** | ||
* Static trust function to trust nothing. | ||
* | ||
*/ | ||
const trustNone = () => false; | ||
/** | ||
* Compile trust function for multiple subnets. | ||
*/ | ||
function trustMulti(subnets) { | ||
return function trust(addr) { | ||
if (!isip(addr)) | ||
return false; | ||
const ip = parseip(addr); | ||
let ipconv; | ||
const kind = ip.kind(); | ||
for (let i = 0; i < subnets.length; i++) { | ||
const subnet = subnets[i]; | ||
const subnetip = subnet[0]; | ||
const subnetkind = subnetip.kind(); | ||
const subnetrange = subnet[1]; | ||
let trusted = ip; | ||
if (kind !== subnetkind) { | ||
if (subnetkind === 'ipv4' && !ip.isIPv4MappedAddress()) | ||
continue; | ||
if (!ipconv) | ||
ipconv = subnetkind === 'ipv4' ? ip.toIPv4Address() : ip.toIPv4MappedAddress(); | ||
trusted = ipconv; | ||
} | ||
if (trusted.match(subnetip, subnetrange)) | ||
return true; | ||
} | ||
return false; | ||
}; | ||
return function trust(addr) { | ||
if (!isip(addr)) | ||
return false; | ||
const ip = parseip(addr); | ||
let ipconv; | ||
const kind = ip.kind(); | ||
for (let i = 0; i < subnets.length; i++) { | ||
const subnet = subnets[i]; | ||
const subnetip = subnet[0]; | ||
const subnetkind = subnetip.kind(); | ||
const subnetrange = subnet[1]; | ||
let trusted = ip; | ||
if (kind !== subnetkind) { | ||
if (subnetkind === "ipv4" && !ip.isIPv4MappedAddress()) | ||
continue; | ||
if (!ipconv) | ||
ipconv = subnetkind === "ipv4" ? ip.toIPv4Address() : ip.toIPv4MappedAddress(); | ||
trusted = ipconv; | ||
} | ||
if (trusted.match(subnetip, subnetrange)) | ||
return true; | ||
} | ||
return false; | ||
}; | ||
} | ||
/** | ||
* Compile trust function for single subnet. | ||
* | ||
* @param subnet | ||
*/ | ||
function trustSingle(subnet) { | ||
const subnetip = subnet[0]; | ||
const subnetkind = subnetip.kind(); | ||
const subnetisipv4 = subnetkind === 'ipv4'; | ||
const subnetrange = subnet[1]; | ||
return function trust(addr) { | ||
if (!isip(addr)) | ||
return false; | ||
let ip = parseip(addr); | ||
const kind = ip.kind(); | ||
if (kind !== subnetkind) { | ||
if (subnetisipv4 && !ip.isIPv4MappedAddress()) | ||
return false; | ||
ip = subnetisipv4 ? ip.toIPv4Address() : ip.toIPv4MappedAddress(); | ||
} | ||
return ip.match(subnetip, subnetrange); | ||
}; | ||
const subnetip = subnet[0]; | ||
const subnetkind = subnetip.kind(); | ||
const subnetisipv4 = subnetkind === "ipv4"; | ||
const subnetrange = subnet[1]; | ||
return function trust(addr) { | ||
if (!isip(addr)) | ||
return false; | ||
let ip = parseip(addr); | ||
const kind = ip.kind(); | ||
if (kind !== subnetkind) { | ||
if (subnetisipv4 && !ip.isIPv4MappedAddress()) | ||
return false; | ||
ip = subnetisipv4 ? ip.toIPv4Address() : ip.toIPv4MappedAddress(); | ||
} | ||
return ip.match(subnetip, subnetrange); | ||
}; | ||
} | ||
export { alladdrs as all, compile, parseIPNotation, proxyaddr }; | ||
export { | ||
alladdrs as all, | ||
compile, | ||
parseIPNotation, | ||
proxyaddr | ||
}; |
{ | ||
"name": "@tinyhttp/proxy-addr", | ||
"version": "2.0.4", | ||
"version": "2.0.5", | ||
"type": "module", | ||
@@ -31,8 +31,10 @@ "description": "proxy-addr rewrite with TypeScript and ESM support", | ||
"dependencies": { | ||
"@tinyhttp/forwarded": "2.0.4", | ||
"@tinyhttp/forwarded": "2.0.5", | ||
"ipaddr.js": "^2.0.1" | ||
}, | ||
"scripts": { | ||
"build": "rollup -c ../../build/defaultConfig.js" | ||
"dev": "vite", | ||
"build": "vite build", | ||
"postbuild": "tsc --emitDeclarationOnly" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
6
7303
172
+ Added@tinyhttp/forwarded@2.0.5(transitive)
- Removed@tinyhttp/forwarded@2.0.4(transitive)
Updated@tinyhttp/forwarded@2.0.5