@@ -12,7 +12,7 @@ const X_FORWARDED_HOST: HeaderName = HeaderName::from_lowercase_str("x-forwarded
1212
1313/// A rust representation of the [forwarded
1414/// header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded).
15- #[ derive( Debug , Clone , Default ) ]
15+ #[ derive( Debug , Clone , Default , PartialEq , Eq ) ]
1616pub struct Forwarded < ' a > {
1717 by : Option < Cow < ' a , str > > ,
1818 forwarded_for : Vec < Cow < ' a , str > > ,
@@ -208,12 +208,12 @@ impl<'a> Forwarded<'a> {
208208 let mut input = input;
209209 let mut forwarded = Forwarded :: new ( ) ;
210210
211- if starts_with_ignore_case ( "for=" , input) {
212- input = forwarded. parse_for ( input) ?;
213- }
214-
215211 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+ }
217217 }
218218
219219 Ok ( forwarded)
@@ -429,8 +429,12 @@ fn match_ignore_case<'a>(start: &'static str, input: &'a str) -> (bool, &'a str)
429429}
430430
431431fn 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+ }
434438}
435439
436440impl std:: fmt:: Display for Forwarded < ' _ > {
@@ -467,6 +471,11 @@ mod tests {
467471 use crate :: { Method :: Get , Request , Response , Result } ;
468472 use url:: Url ;
469473
474+ #[ test]
475+ fn starts_with_ignore_case_can_handle_short_inputs ( ) {
476+ assert ! ( !starts_with_ignore_case( "helloooooo" , "h" ) ) ;
477+ }
478+
470479 #[ test]
471480 fn parsing_for ( ) -> Result < ( ) > {
472481 assert_eq ! (
@@ -641,4 +650,19 @@ mod tests {
641650 assert_eq ! ( forwarded. by( ) , Some ( "by" ) ) ;
642651 Ok ( ( ) )
643652 }
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+ }
644668}
0 commit comments