@@ -5,7 +5,7 @@ import ipaddr, { type IPv6, type IPv4 } from "ipaddr.js"
5
5
type Req = Pick < IncomingMessage , "headers" | "socket" >
6
6
7
7
export type TrustParameter = string | number | string [ ]
8
- export type TrustFunction = ( addr : string | undefined , i : number ) => boolean
8
+ export type TrustFunction = ( addr : IPv4 | IPv6 | undefined , i : number ) => boolean
9
9
export type Trust = TrustFunction | TrustParameter
10
10
11
11
type Subnet = {
@@ -14,8 +14,9 @@ type Subnet = {
14
14
}
15
15
16
16
const DIGIT_REGEXP = / ^ [ 0 - 9 ] + $ /
17
- const isip = ipaddr . isValid
18
- const parseip = ipaddr . parse
17
+ const isIp = ipaddr . isValid
18
+ const parseIp = ipaddr . parse
19
+
19
20
/**
20
21
* Pre-defined IP ranges.
21
22
*/
@@ -55,21 +56,23 @@ const trustNone: TrustFunction = () => false
55
56
* @param req
56
57
* @param trust
57
58
*/
58
- function allAddresses ( req : Req , trust ?: Trust ) : Array < string | undefined > {
59
+ function allAddresses ( req : Req , trust ?: Trust ) : Array < IPv4 | IPv6 | undefined > {
59
60
// get addresses
61
+ const addressGenerator = forwarded ( req )
60
62
61
- const addrs = forwarded ( req )
62
-
63
- if ( trust == null ) return addrs
64
-
63
+ if ( trust == null ) return Array . from ( addressGenerator )
65
64
if ( typeof trust !== "function" ) trust = compile ( trust )
66
65
67
- for ( let i = 0 ; i < addrs . length - 1 ; i ++ ) {
68
- if ( trust ( addrs [ i ] , i ) ) continue
69
- addrs . length = i + 1
66
+ let i = 0
67
+ const addresses : Array < IPv4 | IPv6 | undefined > = [ ]
68
+ for ( const address of addressGenerator ) {
69
+ addresses . push ( address )
70
+ if ( ! trust ( address , i ) ) break
71
+ i += 1
70
72
}
71
- return addrs
73
+ return addresses
72
74
}
75
+
73
76
/**
74
77
* Compile argument into trust function.
75
78
*
@@ -93,6 +96,7 @@ function compile(val: string | number | string[]): TrustFunction {
93
96
}
94
97
return compileTrust ( compileRangeSubnets ( trust ) )
95
98
}
99
+
96
100
/**
97
101
* Compile 'hops' number into trust function.
98
102
*
@@ -108,6 +112,7 @@ function compileHopsTrust(hops: number): TrustFunction {
108
112
function compileRangeSubnets ( arr : string [ ] ) {
109
113
return arr . map ( ( ip ) => parseIPNotation ( ip ) )
110
114
}
115
+
111
116
/**
112
117
* Compile range subnet array into trust function.
113
118
*
@@ -118,6 +123,7 @@ function compileTrust(rangeSubnets: Subnet[]): TrustFunction {
118
123
const len = rangeSubnets . length
119
124
return len === 0 ? trustNone : len === 1 ? trustSingle ( rangeSubnets [ 0 ] ) : trustMulti ( rangeSubnets )
120
125
}
126
+
121
127
/**
122
128
* Parse IP notation string into range subnet.
123
129
*
@@ -128,9 +134,9 @@ export function parseIPNotation(note: string): Subnet {
128
134
const pos = note . lastIndexOf ( "/" )
129
135
const str = pos !== - 1 ? note . substring ( 0 , pos ) : note
130
136
131
- if ( ! isip ( str ) ) throw new TypeError ( `invalid IP address: ${ str } ` )
137
+ if ( ! isIp ( str ) ) throw new TypeError ( `invalid IP address: ${ str } ` )
132
138
133
- let ip = parseip ( str )
139
+ let ip = parseIp ( str )
134
140
const max = ip . kind ( ) === "ipv6" ? 128 : 32
135
141
136
142
if ( pos === - 1 ) {
@@ -142,43 +148,43 @@ export function parseIPNotation(note: string): Subnet {
142
148
let range : number | null = null
143
149
144
150
if ( DIGIT_REGEXP . test ( rangeString ) ) range = Number . parseInt ( rangeString , 10 )
145
- else if ( ip . kind ( ) === "ipv4" && isip ( rangeString ) ) range = parseNetmask ( rangeString )
151
+ else if ( ip . kind ( ) === "ipv4" && isIp ( rangeString ) ) range = parseNetmask ( rangeString )
146
152
147
153
if ( range == null || range <= 0 || range > max ) throw new TypeError ( `invalid range on address: ${ note } ` )
148
154
return { ip, range }
149
155
}
156
+
150
157
/**
151
158
* Parse netmask string into CIDR range.
152
159
*
153
160
* @param netmask
154
161
* @private
155
162
*/
156
163
function parseNetmask ( netmask : string ) {
157
- const ip = parseip ( netmask )
164
+ const ip = parseIp ( netmask )
158
165
return ip . kind ( ) === "ipv4" ? ip . prefixLengthFromSubnetMask ( ) : null
159
166
}
167
+
160
168
/**
161
169
* Determine address of proxied request.
162
170
*
163
171
* @param req
164
172
* @param trust
165
173
* @public
166
174
*/
167
- function proxyAddress ( req : Req , trust : Trust ) : string | undefined {
175
+ function proxyAddress ( req : Req , trust : Trust ) : IPv4 | IPv6 | undefined {
168
176
if ( trust == null ) throw new TypeError ( "trust argument cannot be null-ish" )
169
- const addrs = allAddresses ( req , trust )
177
+ const addresses = allAddresses ( req , trust )
170
178
171
- return addrs [ addrs . length - 1 ]
179
+ return addresses [ addresses . length - 1 ]
172
180
}
173
181
174
182
/**
175
183
* Compile trust function for multiple subnets.
176
184
*/
177
185
function trustMulti ( subnets : Subnet [ ] ) : TrustFunction {
178
- return function trust ( addr : string | undefined ) {
179
- if ( addr == null ) return false
180
- if ( ! isip ( addr ) ) return false
181
- const ip = parseip ( addr )
186
+ return function trust ( ip : IPv4 | IPv6 | undefined ) {
187
+ if ( ip == null ) return false
182
188
let ipconv : IPv4 | IPv6 | null = null
183
189
const kind = ip . kind ( )
184
190
for ( let i = 0 ; i < subnets . length ; i ++ ) {
@@ -197,6 +203,7 @@ function trustMulti(subnets: Subnet[]): TrustFunction {
197
203
return false
198
204
}
199
205
}
206
+
200
207
/**
201
208
* Compile trust function for single subnet.
202
209
*
@@ -205,10 +212,8 @@ function trustMulti(subnets: Subnet[]): TrustFunction {
205
212
function trustSingle ( subnet : Subnet ) : TrustFunction {
206
213
const subnetKind = subnet . ip . kind ( )
207
214
const subnetIsIPv4 = subnetKind === "ipv4"
208
- return function trust ( addr : string | undefined ) {
209
- if ( addr == null ) return false
210
- if ( ! isip ( addr ) ) return false
211
- let ip = parseip ( addr )
215
+ return function trust ( ip : IPv4 | IPv6 | undefined ) {
216
+ if ( ip == null ) return false
212
217
const kind = ip . kind ( )
213
218
if ( kind !== subnetKind ) {
214
219
if ( subnetIsIPv4 && ! ( ip as IPv6 ) . isIPv4MappedAddress ( ) ) return false
@@ -220,3 +225,4 @@ function trustSingle(subnet: Subnet): TrustFunction {
220
225
}
221
226
222
227
export { allAddresses , compile , proxyAddress }
228
+ export type { IPv4 , IPv6 }
0 commit comments