@@ -411,26 +411,32 @@ ffi_fn! {
411411 // and for each one, try to pair the originally cased name with the value.
412412 //
413413 // TODO: consider adding http::HeaderMap::entries() iterator
414- for ( name, idx) in headers. orig_order. get_in_order( ) {
415- //println!("OHEA {:?}", (name, idx));
416- let orig_name = headers. orig_casing. get_all( & name) . nth( * idx) . unwrap( ) ;
417- let value = headers. headers. get_all( name) . iter( ) . nth( * idx) . unwrap( ) ;
418-
419- let name_ptr = orig_name. as_ref( ) . as_ptr( ) ;
420- let name_len = orig_name. as_ref( ) . len( ) ;
421-
422- let val_ptr = value. as_bytes( ) . as_ptr( ) ;
423- let val_len = value. as_bytes( ) . len( ) ;
424-
425- if HYPER_ITER_CONTINUE != func( userdata, name_ptr, name_len, val_ptr, val_len) {
426- return ;
414+ for name in headers. headers. keys( ) {
415+ let mut names = headers. orig_casing. get_all( name) ;
416+
417+ for value in headers. headers. get_all( name) {
418+ let ( name_ptr, name_len) = if let Some ( orig_name) = names. next( ) {
419+ ( orig_name. as_ref( ) . as_ptr( ) , orig_name. as_ref( ) . len( ) )
420+ } else {
421+ (
422+ name. as_str( ) . as_bytes( ) . as_ptr( ) ,
423+ name. as_str( ) . as_bytes( ) . len( ) ,
424+ )
425+ } ;
426+
427+ let val_ptr = value. as_bytes( ) . as_ptr( ) ;
428+ let val_len = value. as_bytes( ) . len( ) ;
429+
430+ if HYPER_ITER_CONTINUE != func( userdata, name_ptr, name_len, val_ptr, val_len) {
431+ return ;
432+ }
427433 }
428434 }
429435 }
430436}
431437
432438ffi_fn ! {
433- /// Iterates the headers passing each name and value pair to the callback.
439+ /// Iterates the headers in the order the were recieved, passing each name and value pair to the callback.
434440 ///
435441 /// The `userdata` pointer is also passed to the callback.
436442 ///
@@ -470,7 +476,7 @@ ffi_fn! {
470476 Ok ( ( name, value, orig_name) ) => {
471477 headers. headers. insert( & name, value) ;
472478 headers. orig_casing. insert( name. clone( ) , orig_name. clone( ) ) ;
473- headers. orig_order. insert( name, orig_name ) ;
479+ headers. orig_order. insert( name) ;
474480 hyper_code:: HYPERE_OK
475481 }
476482 Err ( code) => code,
@@ -490,7 +496,7 @@ ffi_fn! {
490496 Ok ( ( name, value, orig_name) ) => {
491497 headers. headers. append( & name, value) ;
492498 headers. orig_casing. append( & name, orig_name. clone( ) ) ;
493- headers. orig_order. append( name, orig_name ) ;
499+ headers. orig_order. append( name) ;
494500 hyper_code:: HYPERE_OK
495501 }
496502 Err ( code) => code,
@@ -590,4 +596,65 @@ mod tests {
590596 HYPER_ITER_CONTINUE
591597 }
592598 }
599+
600+ #[ cfg( all( feature = "http1" , feature = "ffi" ) ) ]
601+ #[ test]
602+ fn test_headers_foreach_order_preserved ( ) {
603+ let mut headers = hyper_headers:: default ( ) ;
604+
605+ let name1 = b"Set-CookiE" ;
606+ let value1 = b"a=b" ;
607+ hyper_headers_add (
608+ & mut headers,
609+ name1. as_ptr ( ) ,
610+ name1. len ( ) ,
611+ value1. as_ptr ( ) ,
612+ value1. len ( ) ,
613+ ) ;
614+
615+ let name2 = b"Content-Encoding" ;
616+ let value2 = b"gzip" ;
617+ hyper_headers_add (
618+ & mut headers,
619+ name2. as_ptr ( ) ,
620+ name2. len ( ) ,
621+ value2. as_ptr ( ) ,
622+ value2. len ( ) ,
623+ ) ;
624+
625+ let name3 = b"SET-COOKIE" ;
626+ let value3 = b"c=d" ;
627+ hyper_headers_add (
628+ & mut headers,
629+ name3. as_ptr ( ) ,
630+ name3. len ( ) ,
631+ value3. as_ptr ( ) ,
632+ value3. len ( ) ,
633+ ) ;
634+
635+ let mut vec = Vec :: < u8 > :: new ( ) ;
636+ hyper_headers_foreach_ordered ( & headers, concat, & mut vec as * mut _ as * mut c_void ) ;
637+
638+ println ! ( "{}" , std:: str :: from_utf8( & vec) . unwrap( ) ) ;
639+ assert_eq ! ( vec, b"Set-CookiE: a=b\r \n Content-Encoding: gzip\r \n SET-COOKIE: c=d\r \n " ) ;
640+
641+ extern "C" fn concat (
642+ vec : * mut c_void ,
643+ name : * const u8 ,
644+ name_len : usize ,
645+ value : * const u8 ,
646+ value_len : usize ,
647+ ) -> c_int {
648+ unsafe {
649+ let vec = & mut * ( vec as * mut Vec < u8 > ) ;
650+ let name = std:: slice:: from_raw_parts ( name, name_len) ;
651+ let value = std:: slice:: from_raw_parts ( value, value_len) ;
652+ vec. extend ( name) ;
653+ vec. extend ( b": " ) ;
654+ vec. extend ( value) ;
655+ vec. extend ( b"\r \n " ) ;
656+ }
657+ HYPER_ITER_CONTINUE
658+ }
659+ }
593660}
0 commit comments