swc/crates/swc_bundler/tests/.cache/deno/320e912741816078415249d998e4953a923873e4.ts
2021-11-09 20:42:49 +09:00

201 lines
5.3 KiB
TypeScript

// Loaded from https://deno.land/x/proxy_addr@0.0.15/mod.ts
// deno-lint-ignore-file
import { ServerRequest } from 'https://deno.land/std@0.101.0/http/server.ts'
import { default as ipaddr, IPv4, IPv6 } from 'https://cdn.skypack.dev/ipaddr.js'
import { forwarded } from 'https://deno.land/x/forwarded@0.0.9/mod.ts'
const DIGIT_REGEXP = /^[0-9]+$/
const isip = ipaddr.isValid
const parseip = ipaddr.parse
/**
* Pre-defined IP ranges.
*/
const IP_RANGES: Record<string, string[]> = {
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: ServerRequest, trust: ((...args: any[]) => any) | any[] | string[] | string) {
// 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
}
return addrs
}
/**
* Compile argument into trust function.
*
* @param val
*/
function compile(val: string | string[]) {
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]
trust.splice.apply(trust, [i, 1, ...val])
i += val.length - 1
}
return compileTrust(compileRangeSubnets(trust))
}
/**
* Compile `arr` elements into range subnets.
*/
function compileRangeSubnets(arr: any[]) {
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: any[]) {
// Return optimized function based on length
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
*/
export function parseIPNotation(note: string) {
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 as typeof IPv6
if (ip.isIPv4MappedAddress()) ip = ip.toIPv4Address()
}
const max = ip.kind() === 'ipv6' ? 128 : 32
let range: string | number | null = 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 && (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: string) {
const ip = parseip(netmask)
return ip.kind() === 'ipv4' ? ip.prefixLengthFromSubnetMask() : null
}
/**
* Determine address of proxied request.
*
* @param request
* @param trust
* @public
*/
export function proxyaddr(req: ServerRequest, trust: ((...args: any[]) => any) | any[] | string[] | string) {
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: any[]) {
return function trust(addr: string) {
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 as typeof IPv6).isIPv4MappedAddress()) continue
if (!ipconv)
ipconv =
subnetkind === 'ipv4' ? (ip as typeof IPv6).toIPv4Address() : (ip as typeof IPv4).toIPv4MappedAddress()
trusted = ipconv
}
if ((trusted as typeof IPv4).match(subnetip, subnetrange)) return true
}
return false
}
}
/**
* Compile trust function for single subnet.
*
* @param subnet
*/
function trustSingle(subnet: any[]) {
const subnetip = subnet[0]
const subnetkind = subnetip.kind()
const subnetisipv4 = subnetkind === 'ipv4'
const subnetrange = subnet[1]
return function trust(addr: string) {
if (!isip(addr)) return false
let ip = parseip(addr)
const kind = ip.kind()
if (kind !== subnetkind) {
if (subnetisipv4 && !(ip as typeof IPv6).isIPv4MappedAddress()) return false
ip = subnetisipv4 ? (ip as typeof IPv6).toIPv4Address() : (ip as typeof IPv4).toIPv4MappedAddress()
}
return (ip as typeof IPv6).match(subnetip, subnetrange)
}
}
export { alladdrs as all }
export { compile }