@@ -11,7 +11,7 @@ const X_FORWARDED_BY: HeaderName = HeaderName::from_lowercase_str("x-forwarded-b
11
11
12
12
/// A rust representation of the [forwarded
13
13
/// header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded).
14
- #[ derive( Debug , Clone , Default ) ]
14
+ #[ derive( Debug , Clone , Default , PartialEq , Eq ) ]
15
15
pub struct Forwarded < ' a > {
16
16
by : Option < Cow < ' a , str > > ,
17
17
forwarded_for : Vec < Cow < ' a , str > > ,
@@ -197,12 +197,12 @@ impl<'a> Forwarded<'a> {
197
197
let mut input = input;
198
198
let mut forwarded = Forwarded :: new ( ) ;
199
199
200
- if starts_with_ignore_case ( "for=" , input) {
201
- input = forwarded. parse_for ( input) ?;
202
- }
203
-
204
200
while !input. is_empty ( ) {
205
- input = forwarded. parse_forwarded_pair ( input) ?;
201
+ input = if starts_with_ignore_case ( "for=" , input) {
202
+ forwarded. parse_for ( input) ?
203
+ } else {
204
+ forwarded. parse_forwarded_pair ( input) ?
205
+ }
206
206
}
207
207
208
208
Ok ( forwarded)
@@ -442,8 +442,12 @@ fn match_ignore_case<'a>(start: &'static str, input: &'a str) -> (bool, &'a str)
442
442
}
443
443
444
444
fn starts_with_ignore_case ( start : & ' static str , input : & str ) -> bool {
445
- let len = start. len ( ) ;
446
- input[ ..len] . eq_ignore_ascii_case ( start)
445
+ if start. len ( ) <= input. len ( ) {
446
+ let len = start. len ( ) ;
447
+ input[ ..len] . eq_ignore_ascii_case ( start)
448
+ } else {
449
+ false
450
+ }
447
451
}
448
452
449
453
impl std:: fmt:: Display for Forwarded < ' _ > {
@@ -494,6 +498,11 @@ mod tests {
494
498
use crate :: { Method :: Get , Request , Response , Result } ;
495
499
use url:: Url ;
496
500
501
+ #[ test]
502
+ fn starts_with_ignore_case_can_handle_short_inputs ( ) {
503
+ assert ! ( !starts_with_ignore_case( "helloooooo" , "h" ) ) ;
504
+ }
505
+
497
506
#[ test]
498
507
fn parsing_for ( ) -> Result < ( ) > {
499
508
assert_eq ! (
@@ -667,4 +676,19 @@ mod tests {
667
676
assert_eq ! ( forwarded. by( ) , Some ( "by" ) ) ;
668
677
Ok ( ( ) )
669
678
}
679
+
680
+ #[ test]
681
+ fn round_trip ( ) -> Result < ( ) > {
682
+ let inputs = [
683
+ "for=client,for=b,for=c;by=proxy.com;host=example.com;proto=https" ,
684
+ "by=proxy.com;proto=https;host=example.com;for=a,for=b" ,
685
+ ] ;
686
+ for input in inputs {
687
+ let forwarded = Forwarded :: parse ( input) . map_err ( |_| crate :: Error :: new_adhoc ( input) ) ?;
688
+ let header = forwarded. to_header_values ( ) ?. next ( ) . unwrap ( ) ;
689
+ let parsed = Forwarded :: parse ( header. as_str ( ) ) ?;
690
+ assert_eq ! ( forwarded, parsed) ;
691
+ }
692
+ Ok ( ( ) )
693
+ }
670
694
}
0 commit comments