| @@ -92,8 +92,10 @@ impl net::NetworkStream for MockStream { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl net::NetworkConnector for MockStream { | struct MockConnector; | ||||||
|     fn connect<To: ToSocketAddr>(_addr: To, _scheme: &str) -> IoResult<MockStream> { |  | ||||||
|  | impl net::NetworkConnector<MockStream> for MockConnector { | ||||||
|  |     fn connect<To: ToSocketAddr>(&mut self, _addr: To, _scheme: &str) -> IoResult<MockStream> { | ||||||
|         Ok(MockStream::new()) |         Ok(MockStream::new()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -103,8 +105,9 @@ impl net::NetworkConnector for MockStream { | |||||||
| fn bench_mock_hyper(b: &mut test::Bencher) { | fn bench_mock_hyper(b: &mut test::Bencher) { | ||||||
|     let url = "http://127.0.0.1:1337/"; |     let url = "http://127.0.0.1:1337/"; | ||||||
|     b.iter(|| { |     b.iter(|| { | ||||||
|         let mut req = hyper::client::Request::with_stream::<MockStream>( |         let mut req = hyper::client::Request::with_connector( | ||||||
|             hyper::Get, hyper::Url::parse(url).unwrap()).unwrap(); |             hyper::Get, hyper::Url::parse(url).unwrap(), &mut MockConnector | ||||||
|  |         ).unwrap(); | ||||||
|         req.headers_mut().set(Foo); |         req.headers_mut().set(Foo); | ||||||
|  |  | ||||||
|         req |         req | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ use method; | |||||||
| use method::Method::{Get, Post, Delete, Put, Patch, Head, Options}; | use method::Method::{Get, Post, Delete, Put, Patch, Head, Options}; | ||||||
| use header::Headers; | use header::Headers; | ||||||
| use header::common::{mod, Host}; | use header::common::{mod, Host}; | ||||||
| use net::{NetworkStream, NetworkConnector, HttpStream, Fresh, Streaming}; | use net::{NetworkStream, NetworkConnector, HttpConnector, Fresh, Streaming}; | ||||||
| use HttpError::HttpUriError; | use HttpError::HttpUriError; | ||||||
| use http::{HttpWriter, LINE_ENDING}; | use http::{HttpWriter, LINE_ENDING}; | ||||||
| use http::HttpWriter::{ThroughWriter, ChunkedWriter, SizedWriter, EmptyWriter}; | use http::HttpWriter::{ThroughWriter, ChunkedWriter, SizedWriter, EmptyWriter}; | ||||||
| @@ -42,11 +42,12 @@ impl<W> Request<W> { | |||||||
| impl Request<Fresh> { | impl Request<Fresh> { | ||||||
|     /// Create a new client request. |     /// Create a new client request. | ||||||
|     pub fn new(method: method::Method, url: Url) -> HttpResult<Request<Fresh>> { |     pub fn new(method: method::Method, url: Url) -> HttpResult<Request<Fresh>> { | ||||||
|         Request::with_stream::<HttpStream>(method, url) |         let mut conn = HttpConnector; | ||||||
|  |         Request::with_connector(method, url, &mut conn) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Create a new client request with a specific underlying NetworkStream. |     /// Create a new client request with a specific underlying NetworkStream. | ||||||
|     pub fn with_stream<S: NetworkConnector>(method: method::Method, url: Url) -> HttpResult<Request<Fresh>> { |     pub fn with_connector<C: NetworkConnector<S>, S: NetworkStream>(method: method::Method, url: Url, connector: &mut C) -> HttpResult<Request<Fresh>> { | ||||||
|         debug!("{} {}", method, url); |         debug!("{} {}", method, url); | ||||||
|         let host = match url.serialize_host() { |         let host = match url.serialize_host() { | ||||||
|             Some(host) => host, |             Some(host) => host, | ||||||
| @@ -59,7 +60,7 @@ impl Request<Fresh> { | |||||||
|         }; |         }; | ||||||
|         debug!("port={}", port); |         debug!("port={}", port); | ||||||
|  |  | ||||||
|         let stream: S = try!(NetworkConnector::connect((host[], port), url.scheme.as_slice())); |         let stream: S = try!(connector.connect((host[], port), &*url.scheme)); | ||||||
|         let stream = ThroughWriter(BufferedWriter::new(box stream as Box<NetworkStream + Send>)); |         let stream = ThroughWriter(BufferedWriter::new(box stream as Box<NetworkStream + Send>)); | ||||||
|  |  | ||||||
|         let mut headers = Headers::new(); |         let mut headers = Headers::new(); | ||||||
| @@ -210,13 +211,13 @@ mod tests { | |||||||
|     use std::str::from_utf8; |     use std::str::from_utf8; | ||||||
|     use url::Url; |     use url::Url; | ||||||
|     use method::Method::{Get, Head}; |     use method::Method::{Get, Head}; | ||||||
|     use mock::MockStream; |     use mock::{MockStream, MockConnector}; | ||||||
|     use super::Request; |     use super::Request; | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_get_empty_body() { |     fn test_get_empty_body() { | ||||||
|         let req = Request::with_stream::<MockStream>( |         let req = Request::with_connector( | ||||||
|             Get, Url::parse("http://example.dom").unwrap() |             Get, Url::parse("http://example.dom").unwrap(), &mut MockConnector | ||||||
|         ).unwrap(); |         ).unwrap(); | ||||||
|         let req = req.start().unwrap(); |         let req = req.start().unwrap(); | ||||||
|         let stream = *req.body.end().unwrap().into_inner().downcast::<MockStream>().unwrap(); |         let stream = *req.body.end().unwrap().into_inner().downcast::<MockStream>().unwrap(); | ||||||
| @@ -228,8 +229,8 @@ mod tests { | |||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_head_empty_body() { |     fn test_head_empty_body() { | ||||||
|         let req = Request::with_stream::<MockStream>( |         let req = Request::with_connector( | ||||||
|             Head, Url::parse("http://example.dom").unwrap() |             Head, Url::parse("http://example.dom").unwrap(), &mut MockConnector | ||||||
|         ).unwrap(); |         ).unwrap(); | ||||||
|         let req = req.start().unwrap(); |         let req = req.start().unwrap(); | ||||||
|         let stream = *req.body.end().unwrap().into_inner().downcast::<MockStream>().unwrap(); |         let stream = *req.body.end().unwrap().into_inner().downcast::<MockStream>().unwrap(); | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								src/http.rs
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								src/http.rs
									
									
									
									
									
								
							| @@ -190,6 +190,31 @@ impl<W: Writer> HttpWriter<W> { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /// Access the inner Writer. | ||||||
|  |     #[inline] | ||||||
|  |     pub fn get_ref<'a>(&'a self) -> &'a W { | ||||||
|  |         match *self { | ||||||
|  |             ThroughWriter(ref w) => w, | ||||||
|  |             ChunkedWriter(ref w) => w, | ||||||
|  |             SizedWriter(ref w, _) => w, | ||||||
|  |             EmptyWriter(ref w) => w, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Access the inner Writer mutably. | ||||||
|  |     /// | ||||||
|  |     /// Warning: You should not write to this directly, as you can corrupt | ||||||
|  |     /// the state. | ||||||
|  |     #[inline] | ||||||
|  |     pub fn get_mut<'a>(&'a mut self) -> &'a mut W { | ||||||
|  |         match *self { | ||||||
|  |             ThroughWriter(ref mut w) => w, | ||||||
|  |             ChunkedWriter(ref mut w) => w, | ||||||
|  |             SizedWriter(ref mut w, _) => w, | ||||||
|  |             EmptyWriter(ref mut w) => w, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /// Ends the HttpWriter, and returns the underlying Writer. |     /// Ends the HttpWriter, and returns the underlying Writer. | ||||||
|     /// |     /// | ||||||
|     /// A final `write()` is called with an empty message, and then flushed. |     /// A final `write()` is called with an empty message, and then flushed. | ||||||
|   | |||||||
| @@ -61,14 +61,15 @@ impl Writer for MockStream { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl NetworkStream for MockStream { | impl NetworkStream for MockStream { | ||||||
|  |  | ||||||
|     fn peer_name(&mut self) -> IoResult<SocketAddr> { |     fn peer_name(&mut self) -> IoResult<SocketAddr> { | ||||||
|         Ok(from_str("127.0.0.1:1337").unwrap()) |         Ok(from_str("127.0.0.1:1337").unwrap()) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl NetworkConnector for MockStream { | pub struct MockConnector; | ||||||
|     fn connect<To: ToSocketAddr>(_addr: To, _scheme: &str) -> IoResult<MockStream> { |  | ||||||
|  | impl NetworkConnector<MockStream> for MockConnector { | ||||||
|  |     fn connect<To: ToSocketAddr>(&mut self, _addr: To, _scheme: &str) -> IoResult<MockStream> { | ||||||
|         Ok(MockStream::new()) |         Ok(MockStream::new()) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								src/net.rs
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								src/net.rs
									
									
									
									
									
								
							| @@ -9,7 +9,6 @@ use std::io::net::ip::{SocketAddr, ToSocketAddr}; | |||||||
| use std::io::net::tcp::{TcpStream, TcpListener, TcpAcceptor}; | use std::io::net::tcp::{TcpStream, TcpListener, TcpAcceptor}; | ||||||
| use std::mem::{mod, transmute, transmute_copy}; | use std::mem::{mod, transmute, transmute_copy}; | ||||||
| use std::raw::{mod, TraitObject}; | use std::raw::{mod, TraitObject}; | ||||||
| use std::sync::{Arc, Mutex}; |  | ||||||
|  |  | ||||||
| use uany::UncheckedBoxAnyDowncast; | use uany::UncheckedBoxAnyDowncast; | ||||||
| use openssl::ssl::{SslStream, SslContext}; | use openssl::ssl::{SslStream, SslContext}; | ||||||
| @@ -53,9 +52,9 @@ pub trait NetworkStream: Stream + Any + Clone + Send { | |||||||
| } | } | ||||||
|  |  | ||||||
| /// A connector creates a NetworkStream. | /// A connector creates a NetworkStream. | ||||||
| pub trait NetworkConnector: NetworkStream { | pub trait NetworkConnector<S: NetworkStream> { | ||||||
|     /// Connect to a remote address. |     /// Connect to a remote address. | ||||||
|     fn connect<To: ToSocketAddr>(addr: To, scheme: &str) -> IoResult<Self>; |     fn connect<To: ToSocketAddr>(&mut self, addr: To, scheme: &str) -> IoResult<S>; | ||||||
| } | } | ||||||
|  |  | ||||||
| impl fmt::Show for Box<NetworkStream + Send> { | impl fmt::Show for Box<NetworkStream + Send> { | ||||||
| @@ -189,11 +188,7 @@ pub enum HttpStream { | |||||||
|     /// A stream over the HTTP protocol. |     /// A stream over the HTTP protocol. | ||||||
|     Http(TcpStream), |     Http(TcpStream), | ||||||
|     /// A stream over the HTTP protocol, protected by SSL. |     /// A stream over the HTTP protocol, protected by SSL. | ||||||
|     // You may be asking wtf an Arc and Mutex? That's because SslStream |     Https(SslStream<TcpStream>), | ||||||
|     // doesn't implement Clone, and we need Clone to use the stream for |  | ||||||
|     // both the Request and Response. |  | ||||||
|     // FIXME: https://github.com/sfackler/rust-openssl/issues/6 |  | ||||||
|     Https(Arc<Mutex<SslStream<TcpStream>>>, SocketAddr), |  | ||||||
| } | } | ||||||
|  |  | ||||||
| impl Reader for HttpStream { | impl Reader for HttpStream { | ||||||
| @@ -201,7 +196,7 @@ impl Reader for HttpStream { | |||||||
|     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { |     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { | ||||||
|         match *self { |         match *self { | ||||||
|             Http(ref mut inner) => inner.read(buf), |             Http(ref mut inner) => inner.read(buf), | ||||||
|             Https(ref mut inner, _) => inner.lock().read(buf) |             Https(ref mut inner) => inner.read(buf) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -211,30 +206,32 @@ impl Writer for HttpStream { | |||||||
|     fn write(&mut self, msg: &[u8]) -> IoResult<()> { |     fn write(&mut self, msg: &[u8]) -> IoResult<()> { | ||||||
|         match *self { |         match *self { | ||||||
|             Http(ref mut inner) => inner.write(msg), |             Http(ref mut inner) => inner.write(msg), | ||||||
|             Https(ref mut inner, _) => inner.lock().write(msg) |             Https(ref mut inner) => inner.write(msg) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     #[inline] |     #[inline] | ||||||
|     fn flush(&mut self) -> IoResult<()> { |     fn flush(&mut self) -> IoResult<()> { | ||||||
|         match *self { |         match *self { | ||||||
|             Http(ref mut inner) => inner.flush(), |             Http(ref mut inner) => inner.flush(), | ||||||
|             Https(ref mut inner, _) => inner.lock().flush(), |             Https(ref mut inner) => inner.flush(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| impl NetworkStream for HttpStream { | impl NetworkStream for HttpStream { | ||||||
|     fn peer_name(&mut self) -> IoResult<SocketAddr> { |     fn peer_name(&mut self) -> IoResult<SocketAddr> { | ||||||
|         match *self { |         match *self { | ||||||
|             Http(ref mut inner) => inner.peer_name(), |             Http(ref mut inner) => inner.peer_name(), | ||||||
|             Https(_, addr) => Ok(addr) |             Https(ref mut inner) => inner.get_mut().peer_name() | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl NetworkConnector for HttpStream { | /// A connector that will produce HttpStreams. | ||||||
|     fn connect<To: ToSocketAddr>(addr: To, scheme: &str) -> IoResult<HttpStream> { | pub struct HttpConnector; | ||||||
|  |  | ||||||
|  | impl NetworkConnector<HttpStream> for HttpConnector { | ||||||
|  |     fn connect<To: ToSocketAddr>(&mut self, addr: To, scheme: &str) -> IoResult<HttpStream> { | ||||||
|         match scheme { |         match scheme { | ||||||
|             "http" => { |             "http" => { | ||||||
|                 debug!("http scheme"); |                 debug!("http scheme"); | ||||||
| @@ -242,13 +239,10 @@ impl NetworkConnector for HttpStream { | |||||||
|             }, |             }, | ||||||
|             "https" => { |             "https" => { | ||||||
|                 debug!("https scheme"); |                 debug!("https scheme"); | ||||||
|                 let mut stream = try!(TcpStream::connect(addr)); |                 let stream = try!(TcpStream::connect(addr)); | ||||||
|                 // we can't access the tcp stream once it's wrapped in an |  | ||||||
|                 // SslStream, so grab the ip address now, just in case. |  | ||||||
|                 let peer_addr = try!(stream.peer_name()); |  | ||||||
|                 let context = try!(SslContext::new(Sslv23).map_err(lift_ssl_error)); |                 let context = try!(SslContext::new(Sslv23).map_err(lift_ssl_error)); | ||||||
|                 let stream = try!(SslStream::new(&context, stream).map_err(lift_ssl_error)); |                 let stream = try!(SslStream::new(&context, stream).map_err(lift_ssl_error)); | ||||||
|                 Ok(Https(Arc::new(Mutex::new(stream)), peer_addr)) |                 Ok(Https(stream)) | ||||||
|             }, |             }, | ||||||
|             _ => { |             _ => { | ||||||
|                 Err(IoError { |                 Err(IoError { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user