feat(client): add HttpMessage trait
				
					
				
			This commit is contained in:
		| @@ -185,6 +185,7 @@ pub mod server; | |||||||
| pub mod status; | pub mod status; | ||||||
| pub mod uri; | pub mod uri; | ||||||
| pub mod version; | pub mod version; | ||||||
|  | pub mod message; | ||||||
|  |  | ||||||
|  |  | ||||||
| /// Re-exporting the mime crate, for convenience. | /// Re-exporting the mime crate, for convenience. | ||||||
|   | |||||||
							
								
								
									
										114
									
								
								src/message.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								src/message.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | |||||||
|  | //! Defines the `HttpMessage` trait that serves to encapsulate the operations of a single | ||||||
|  | //! request-response cycle on any HTTP connection. | ||||||
|  |  | ||||||
|  | use std::fmt::Debug; | ||||||
|  | use std::any::{Any, TypeId}; | ||||||
|  | use std::io::{Read, Write}; | ||||||
|  |  | ||||||
|  | use std::mem; | ||||||
|  |  | ||||||
|  | use typeable::Typeable; | ||||||
|  |  | ||||||
|  | use header::Headers; | ||||||
|  | use http::RawStatus; | ||||||
|  | use url::Url; | ||||||
|  |  | ||||||
|  | use method; | ||||||
|  | use version; | ||||||
|  | use traitobject; | ||||||
|  |  | ||||||
|  | /// Describes a request. | ||||||
|  | #[derive(Clone, Debug)] | ||||||
|  | pub struct RequestHead { | ||||||
|  |     /// The headers of the request | ||||||
|  |     pub headers: Headers, | ||||||
|  |     /// The method of the request | ||||||
|  |     pub method: method::Method, | ||||||
|  |     /// The URL of the request | ||||||
|  |     pub url: Url, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// Describes a response. | ||||||
|  | #[derive(Clone, Debug)] | ||||||
|  | pub struct ResponseHead { | ||||||
|  |     /// The headers of the reponse | ||||||
|  |     pub headers: Headers, | ||||||
|  |     /// The raw status line of the response | ||||||
|  |     pub raw_status: RawStatus, | ||||||
|  |     /// The HTTP/2 version which generated the response | ||||||
|  |     pub version: version::HttpVersion, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// The trait provides an API for sending an receiving HTTP messages. | ||||||
|  | pub trait HttpMessage: Write + Read + Send + Any + Typeable + Debug { | ||||||
|  |     /// Initiates a new outgoing request. | ||||||
|  |     /// | ||||||
|  |     /// Only the request's head is provided (in terms of the `RequestHead` struct). | ||||||
|  |     /// | ||||||
|  |     /// After this, the `HttpMessage` instance can be used as an `io::Write` in order to write the | ||||||
|  |     /// body of the request. | ||||||
|  |     fn set_outgoing(&mut self, head: RequestHead) -> ::Result<RequestHead>; | ||||||
|  |     /// Obtains the incoming response and returns its head (i.e. the `ResponseHead` struct) | ||||||
|  |     /// | ||||||
|  |     /// After this, the `HttpMessage` instance can be used as an `io::Read` in order to read out | ||||||
|  |     /// the response body. | ||||||
|  |     fn get_incoming(&mut self) -> ::Result<ResponseHead>; | ||||||
|  |  | ||||||
|  |     /// Closes the underlying HTTP connection. | ||||||
|  |     fn close_connection(&mut self) -> ::Result<()>; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl HttpMessage { | ||||||
|  |     unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T { | ||||||
|  |         mem::transmute(traitobject::data(self)) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T { | ||||||
|  |         mem::transmute(traitobject::data_mut(self)) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     unsafe fn downcast_unchecked<T: 'static>(self: Box<HttpMessage>) -> Box<T>  { | ||||||
|  |         let raw: *mut HttpMessage = mem::transmute(self); | ||||||
|  |         mem::transmute(traitobject::data_mut(raw)) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl HttpMessage { | ||||||
|  |     /// Is the underlying type in this trait object a T? | ||||||
|  |     #[inline] | ||||||
|  |     pub fn is<T: Any>(&self) -> bool { | ||||||
|  |         (*self).get_type() == TypeId::of::<T>() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// If the underlying type is T, get a reference to the contained data. | ||||||
|  |     #[inline] | ||||||
|  |     pub fn downcast_ref<T: Any>(&self) -> Option<&T> { | ||||||
|  |         if self.is::<T>() { | ||||||
|  |             Some(unsafe { self.downcast_ref_unchecked() }) | ||||||
|  |         } else { | ||||||
|  |             None | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// If the underlying type is T, get a mutable reference to the contained | ||||||
|  |     /// data. | ||||||
|  |     #[inline] | ||||||
|  |     pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> { | ||||||
|  |         if self.is::<T>() { | ||||||
|  |             Some(unsafe { self.downcast_mut_unchecked() }) | ||||||
|  |         } else { | ||||||
|  |             None | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// If the underlying type is T, extract it. | ||||||
|  |     #[inline] | ||||||
|  |     pub fn downcast<T: Any>(self: Box<HttpMessage>) | ||||||
|  |             -> Result<Box<T>, Box<HttpMessage>> { | ||||||
|  |         if self.is::<T>() { | ||||||
|  |             Ok(unsafe { self.downcast_unchecked() }) | ||||||
|  |         } else { | ||||||
|  |             Err(self) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user