@@ -94,7 +94,7 @@ impl Default for Server {
94
94
match env_optional :: < String > ( "WEB_PAGE_OFFSET_CIDR_BLOCKLIST" ) {
95
95
None => vec ! [ ] ,
96
96
Some ( s) if s. is_empty ( ) => vec ! [ ] ,
97
- Some ( s) => s. split ( ',' ) . map ( String :: from ) . collect ( ) ,
97
+ Some ( s) => s. split ( ',' ) . map ( parse_cidr_block ) . collect ( ) ,
98
98
} ;
99
99
100
100
let base = Base :: from_environment ( ) ;
@@ -116,7 +116,7 @@ impl Default for Server {
116
116
blocked_traffic : blocked_traffic ( ) ,
117
117
max_allowed_page_offset : env_optional ( "WEB_MAX_ALLOWED_PAGE_OFFSET" ) . unwrap_or ( 200 ) ,
118
118
page_offset_ua_blocklist,
119
- page_offset_cidr_blocklist : parse_cidr_blocks ( & page_offset_cidr_blocklist ) ,
119
+ page_offset_cidr_blocklist,
120
120
excluded_crate_names,
121
121
domain_name : domain_name ( ) ,
122
122
allowed_origins,
@@ -158,7 +158,7 @@ pub(crate) fn domain_name() -> String {
158
158
dotenv:: var ( "DOMAIN_NAME" ) . unwrap_or_else ( |_| "crates.io" . into ( ) )
159
159
}
160
160
161
- /// Parses list of CIDR block strings to valid `IpNetwork` structs .
161
+ /// Parses a CIDR block string to a valid `IpNetwork` struct .
162
162
///
163
163
/// The purpose is to be able to block IP ranges that overload the API that uses pagination.
164
164
///
@@ -167,30 +167,25 @@ pub(crate) fn domain_name() -> String {
167
167
/// * at least 16 for IPv4 based CIDRs.
168
168
/// * at least 64 for IPv6 based CIDRs
169
169
///
170
- fn parse_cidr_blocks ( blocks : & [ String ] ) -> Vec < IpNetwork > {
171
- blocks
172
- . iter ( )
173
- . map ( |block| {
174
- let network = block. parse :: < IpNetwork > ( ) ;
175
- match network {
176
- Ok ( cidr) => {
177
- let host_prefix = match cidr {
178
- IpNetwork :: V4 ( _) => 16 ,
179
- IpNetwork :: V6 ( _) => 64 ,
180
- } ;
181
- if cidr. prefix ( ) < host_prefix {
182
- panic ! (
183
- "WEB_PAGE_OFFSET_CIDR_BLOCKLIST only allows CIDR blocks with a host prefix \
170
+ fn parse_cidr_block ( block : & str ) -> IpNetwork {
171
+ let network = block. parse ( ) ;
172
+ match network {
173
+ Ok ( cidr) => {
174
+ let host_prefix = match cidr {
175
+ IpNetwork :: V4 ( _) => 16 ,
176
+ IpNetwork :: V6 ( _) => 64 ,
177
+ } ;
178
+ if cidr. prefix ( ) < host_prefix {
179
+ panic ! (
180
+ "WEB_PAGE_OFFSET_CIDR_BLOCKLIST only allows CIDR blocks with a host prefix \
184
181
of at least 16 bits (IPv4) or 64 bits (IPv6)."
185
- ) ;
186
- } else {
187
- cidr
188
- }
189
- } ,
190
- Err ( _) => panic ! ( "WEB_PAGE_OFFSET_CIDR_BLOCKLIST must contain IPv4 or IPv6 CIDR blocks." ) ,
182
+ ) ;
183
+ } else {
184
+ cidr
191
185
}
192
- } )
193
- . collect :: < Vec < _ > > ( )
186
+ }
187
+ Err ( _) => panic ! ( "WEB_PAGE_OFFSET_CIDR_BLOCKLIST must contain IPv4 or IPv6 CIDR blocks." ) ,
188
+ }
194
189
}
195
190
196
191
fn blocked_traffic ( ) -> Vec < ( String , Vec < String > ) > {
@@ -235,35 +230,40 @@ fn parse_traffic_patterns_splits_on_comma_and_looks_for_equal_sign() {
235
230
236
231
#[ test]
237
232
fn parse_cidr_block_list_successfully ( ) {
238
- let cidr_blocks = vec ! [ "127.0.0.1/24" . to_string( ) , "192.168.0.1/31" . to_string( ) ] ;
239
-
240
- let blocks = parse_cidr_blocks ( & cidr_blocks) ;
241
233
assert_eq ! (
242
- vec![
243
- "127.0.0.1/24" . parse:: <IpNetwork >( ) . unwrap( ) ,
244
- "192.168.0.1/31" . parse:: <IpNetwork >( ) . unwrap( ) ,
245
- ] ,
246
- blocks,
234
+ parse_cidr_block( "127.0.0.1/24" ) ,
235
+ "127.0.0.1/24" . parse:: <IpNetwork >( ) . unwrap( )
236
+ ) ;
237
+ assert_eq ! (
238
+ parse_cidr_block( "192.168.0.1/31" ) ,
239
+ "192.168.0.1/31" . parse:: <IpNetwork >( ) . unwrap( )
247
240
) ;
248
241
}
249
242
250
243
#[ test]
251
244
#[ should_panic]
252
245
fn parse_cidr_blocks_panics_when_host_ipv4_prefix_is_too_low ( ) {
253
- parse_cidr_blocks ( & [ "127.0.0.1/8" . to_string ( ) ] ) ;
246
+ parse_cidr_block ( "127.0.0.1/8" ) ;
254
247
}
255
248
256
249
#[ test]
257
250
#[ should_panic]
258
251
fn parse_cidr_blocks_panics_when_host_ipv6_prefix_is_too_low ( ) {
259
- parse_cidr_blocks ( & [ "2001:0db8:0123:4567:89ab:cdef:1234:5678/56" . to_string ( ) ] ) ;
252
+ parse_cidr_block ( "2001:0db8:0123:4567:89ab:cdef:1234:5678/56" ) ;
260
253
}
261
254
262
255
#[ test]
263
256
fn parse_ipv6_based_cidr_blocks ( ) {
264
- let input = vec ! [
265
- "2002::1234:abcd:ffff:c0a8:101/64" . to_string( ) ,
266
- "2001:0db8:0123:4567:89ab:cdef:1234:5678/92" . to_string( ) ,
267
- ] ;
268
- assert_eq ! ( 2 , parse_cidr_blocks( & input) . len( ) ) ;
257
+ assert_eq ! (
258
+ parse_cidr_block( "2002::1234:abcd:ffff:c0a8:101/64" ) ,
259
+ "2002::1234:abcd:ffff:c0a8:101/64"
260
+ . parse:: <IpNetwork >( )
261
+ . unwrap( )
262
+ ) ;
263
+ assert_eq ! (
264
+ parse_cidr_block( "2001:0db8:0123:4567:89ab:cdef:1234:5678/92" ) ,
265
+ "2001:0db8:0123:4567:89ab:cdef:1234:5678/92"
266
+ . parse:: <IpNetwork >( )
267
+ . unwrap( )
268
+ ) ;
269
269
}
0 commit comments