@@ -12,7 +12,7 @@ const X_FORWARDED_HOST: HeaderName = HeaderName::from_lowercase_str("x-forwarded
12
12
13
13
/// A rust representation of the [forwarded
14
14
/// header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded).
15
- #[ derive( Debug , Clone , Default ) ]
15
+ #[ derive( Debug , Clone , Default , PartialEq , Eq ) ]
16
16
pub struct Forwarded < ' a > {
17
17
by : Option < Cow < ' a , str > > ,
18
18
forwarded_for : Vec < Cow < ' a , str > > ,
@@ -208,12 +208,12 @@ impl<'a> Forwarded<'a> {
208
208
let mut input = input;
209
209
let mut forwarded = Forwarded :: new ( ) ;
210
210
211
- if starts_with_ignore_case ( "for=" , input) {
212
- input = forwarded. parse_for ( input) ?;
213
- }
214
-
215
211
while !input. is_empty ( ) {
216
- input = forwarded. parse_forwarded_pair ( input) ?;
212
+ input = if starts_with_ignore_case ( "for=" , input) {
213
+ forwarded. parse_for ( input) ?
214
+ } else {
215
+ forwarded. parse_forwarded_pair ( input) ?
216
+ }
217
217
}
218
218
219
219
Ok ( forwarded)
@@ -429,8 +429,12 @@ fn match_ignore_case<'a>(start: &'static str, input: &'a str) -> (bool, &'a str)
429
429
}
430
430
431
431
fn starts_with_ignore_case ( start : & ' static str , input : & str ) -> bool {
432
- let len = start. len ( ) ;
433
- input[ ..len] . eq_ignore_ascii_case ( start)
432
+ if start. len ( ) <= input. len ( ) {
433
+ let len = start. len ( ) ;
434
+ input[ ..len] . eq_ignore_ascii_case ( start)
435
+ } else {
436
+ false
437
+ }
434
438
}
435
439
436
440
impl std:: fmt:: Display for Forwarded < ' _ > {
@@ -467,6 +471,11 @@ mod tests {
467
471
use crate :: { Method :: Get , Request , Response , Result } ;
468
472
use url:: Url ;
469
473
474
+ #[ test]
475
+ fn starts_with_ignore_case_can_handle_short_inputs ( ) {
476
+ assert ! ( !starts_with_ignore_case( "helloooooo" , "h" ) ) ;
477
+ }
478
+
470
479
#[ test]
471
480
fn parsing_for ( ) -> Result < ( ) > {
472
481
assert_eq ! (
@@ -641,4 +650,19 @@ mod tests {
641
650
assert_eq ! ( forwarded. by( ) , Some ( "by" ) ) ;
642
651
Ok ( ( ) )
643
652
}
653
+
654
+ #[ test]
655
+ fn round_trip ( ) -> Result < ( ) > {
656
+ let inputs = [
657
+ "for=client,for=b,for=c;by=proxy.com;host=example.com;proto=https" ,
658
+ "by=proxy.com;proto=https;host=example.com;for=a,for=b" ,
659
+ ] ;
660
+ for input in inputs {
661
+ let forwarded = Forwarded :: parse ( input) . map_err ( |_| crate :: Error :: new_adhoc ( input) ) ?;
662
+ let header = forwarded. header_value ( ) ;
663
+ let parsed = Forwarded :: parse ( header. as_str ( ) ) ?;
664
+ assert_eq ! ( forwarded, parsed) ;
665
+ }
666
+ Ok ( ( ) )
667
+ }
644
668
}
0 commit comments