fix(client): be resilient to invalid response bodies
When an Http11Message knows that the previous response should not have included a body per RFC7230, and fails to parse the following response, the bytes are shuffled along, checking for the start of the next response. Closes #640
This commit is contained in:
		
							
								
								
									
										57
									
								
								src/mock.rs
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								src/mock.rs
									
									
									
									
									
								
							| @@ -19,6 +19,7 @@ use net::{NetworkStream, NetworkConnector}; | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct MockStream { | ||||
|     pub read: Cursor<Vec<u8>>, | ||||
|     next_reads: Vec<Vec<u8>>, | ||||
|     pub write: Vec<u8>, | ||||
|     pub is_closed: bool, | ||||
|     pub error_on_write: bool, | ||||
| @@ -40,21 +41,15 @@ impl MockStream { | ||||
|         MockStream::with_input(b"") | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "timeouts"))] | ||||
|     pub fn with_input(input: &[u8]) -> MockStream { | ||||
|         MockStream { | ||||
|             read: Cursor::new(input.to_vec()), | ||||
|             write: vec![], | ||||
|             is_closed: false, | ||||
|             error_on_write: false, | ||||
|             error_on_read: false, | ||||
|         } | ||||
|         MockStream::with_responses(vec![input]) | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "timeouts")] | ||||
|     pub fn with_input(input: &[u8]) -> MockStream { | ||||
|     pub fn with_responses(mut responses: Vec<&[u8]>) -> MockStream { | ||||
|         MockStream { | ||||
|             read: Cursor::new(input.to_vec()), | ||||
|             read: Cursor::new(responses.remove(0).to_vec()), | ||||
|             next_reads: responses.into_iter().map(|arr| arr.to_vec()).collect(), | ||||
|             write: vec![], | ||||
|             is_closed: false, | ||||
|             error_on_write: false, | ||||
| @@ -63,6 +58,18 @@ impl MockStream { | ||||
|             write_timeout: Cell::new(None), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     #[cfg(not(feature = "timeouts"))] | ||||
|     pub fn with_responses(mut responses: Vec<&[u8]>) -> MockStream { | ||||
|         MockStream { | ||||
|             read: Cursor::new(responses.remove(0).to_vec()), | ||||
|             next_reads: responses.into_iter().map(|arr| arr.to_vec()).collect(), | ||||
|             write: vec![], | ||||
|             is_closed: false, | ||||
|             error_on_write: false, | ||||
|             error_on_read: false, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Read for MockStream { | ||||
| @@ -70,7 +77,17 @@ impl Read for MockStream { | ||||
|         if self.error_on_read { | ||||
|             Err(io::Error::new(io::ErrorKind::Other, "mock error")) | ||||
|         } else { | ||||
|             self.read.read(buf) | ||||
|             match self.read.read(buf) { | ||||
|                 Ok(n) => { | ||||
|                     if self.read.position() as usize == self.read.get_ref().len() { | ||||
|                         if self.next_reads.len() > 0 { | ||||
|                             self.read = Cursor::new(self.next_reads.remove(0)); | ||||
|                         } | ||||
|                     } | ||||
|                     Ok(n) | ||||
|                 }, | ||||
|                 r => r | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -191,7 +208,7 @@ macro_rules! mock_connector ( | ||||
|  | ||||
|         struct $name; | ||||
|  | ||||
|         impl ::net::NetworkConnector for $name { | ||||
|         impl $crate::net::NetworkConnector for $name { | ||||
|             type Stream = ::mock::MockStream; | ||||
|             fn connect(&self, host: &str, port: u16, scheme: &str) | ||||
|                     -> $crate::Result<::mock::MockStream> { | ||||
| @@ -210,7 +227,21 @@ macro_rules! mock_connector ( | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     ) | ||||
|     ); | ||||
|  | ||||
|     ($name:ident { $($response:expr),+ }) => ( | ||||
|         struct $name; | ||||
|  | ||||
|         impl $crate::net::NetworkConnector for $name { | ||||
|             type Stream = $crate::mock::MockStream; | ||||
|             fn connect(&self, _: &str, _: u16, _: &str) | ||||
|                     -> $crate::Result<$crate::mock::MockStream> { | ||||
|                 Ok($crate::mock::MockStream::with_responses(vec![ | ||||
|                     $($response),+ | ||||
|                 ])) | ||||
|             } | ||||
|         } | ||||
|     ); | ||||
| ); | ||||
|  | ||||
| impl TransportStream for MockStream { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user