diff --git a/benches/client.rs b/benches/client.rs index 9059ec75..9e26d39b 100644 --- a/benches/client.rs +++ b/benches/client.rs @@ -8,7 +8,7 @@ use std::fmt; use std::io::{self, Read, Write, Cursor}; use std::net::SocketAddr; -use hyper::net; +use hyper::net::{self, ContextVerifier}; static README: &'static [u8] = include_bytes!("../README.md"); @@ -83,6 +83,9 @@ impl net::NetworkConnector for MockConnector { Ok(MockStream::new()) } + fn set_ssl_verifier(&mut self, _verifier: ContextVerifier) { + // pass + } } #[bench] diff --git a/src/client/mod.rs b/src/client/mod.rs index 4d1a5be4..d978969a 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -147,6 +147,10 @@ impl + Send, S: NetworkStream + Send> NetworkConne -> ::Result> { Ok(try!(self.0.connect(host, port, scheme)).into()) } + #[inline] + fn set_ssl_verifier(&mut self, verifier: ContextVerifier) { + self.0.set_ssl_verifier(verifier); + } } struct Connector(Box> + Send>); @@ -158,6 +162,10 @@ impl NetworkConnector for Connector { -> ::Result> { Ok(try!(self.0.connect(host, port, scheme)).into()) } + #[inline] + fn set_ssl_verifier(&mut self, verifier: ContextVerifier) { + self.0.set_ssl_verifier(verifier); + } } /// Options for an individual Request. diff --git a/src/client/pool.rs b/src/client/pool.rs index 0f570cc3..bf18402c 100644 --- a/src/client/pool.rs +++ b/src/client/pool.rs @@ -5,7 +5,7 @@ use std::io::{self, Read, Write}; use std::net::{SocketAddr, Shutdown}; use std::sync::{Arc, Mutex}; -use net::{NetworkConnector, NetworkStream, HttpConnector}; +use net::{NetworkConnector, NetworkStream, HttpConnector, ContextVerifier}; /// The `NetworkConnector` that behaves as a connection pool used by hyper's `Client`. pub struct Pool { @@ -119,6 +119,10 @@ impl, S: NetworkStream + Send> NetworkConnector fo pool: self.inner.clone() }) } + #[inline] + fn set_ssl_verifier(&mut self, verifier: ContextVerifier) { + self.connector.set_ssl_verifier(verifier); + } } /// A Stream that will try to be returned to the Pool when dropped. @@ -184,8 +188,9 @@ impl Drop for PooledStream { #[cfg(test)] mod tests { use std::net::Shutdown; - use mock::MockConnector; + use mock::{MockConnector, ChannelMockConnector}; use net::{NetworkConnector, NetworkStream}; + use std::sync::mpsc; use super::{Pool, key}; @@ -223,5 +228,19 @@ mod tests { assert_eq!(locked.conns.len(), 0); } + /// Tests that the `Pool::set_ssl_verifier` method sets the SSL verifier of + /// the underlying `Connector` instance that it uses. + #[test] + fn test_set_ssl_verifier_delegates_to_connector() { + let (tx, rx) = mpsc::channel(); + let mut pool = Pool::with_connector( + Default::default(), ChannelMockConnector::new(tx)); + pool.set_ssl_verifier(Box::new(|_| { })); + + match rx.try_recv() { + Ok(meth) => assert_eq!(meth, "set_ssl_verifier"), + _ => panic!("Expected a call to `set_ssl_verifier`"), + }; + } } diff --git a/src/mock.rs b/src/mock.rs index 9cbd022d..817aa22d 100644 --- a/src/mock.rs +++ b/src/mock.rs @@ -1,8 +1,9 @@ use std::fmt; use std::io::{self, Read, Write, Cursor}; use std::net::SocketAddr; +use std::sync::mpsc::Sender; -use net::{NetworkStream, NetworkConnector}; +use net::{NetworkStream, NetworkConnector, ContextVerifier}; pub struct MockStream { pub read: Cursor>, @@ -76,6 +77,39 @@ impl NetworkConnector for MockConnector { fn connect(&mut self, _host: &str, _port: u16, _scheme: &str) -> ::Result { Ok(MockStream::new()) } + + fn set_ssl_verifier(&mut self, _verifier: ContextVerifier) { + // pass + } +} + +/// A mock implementation of the `NetworkConnector` trait that keeps track of all calls to its +/// methods by sending corresponding messages onto a channel. +/// +/// Otherwise, it behaves the same as `MockConnector`. +pub struct ChannelMockConnector { + calls: Sender, +} + +impl ChannelMockConnector { + pub fn new(calls: Sender) -> ChannelMockConnector { + ChannelMockConnector { calls: calls } + } +} + +impl NetworkConnector for ChannelMockConnector { + type Stream = MockStream; + #[inline] + fn connect(&mut self, _host: &str, _port: u16, _scheme: &str) + -> ::Result { + self.calls.send("connect".into()).unwrap(); + Ok(MockStream::new()) + } + + #[inline] + fn set_ssl_verifier(&mut self, _verifier: ContextVerifier) { + self.calls.send("set_ssl_verifier".into()).unwrap(); + } } /// new connectors must be created if you wish to intercept requests. @@ -107,6 +141,9 @@ macro_rules! mock_connector ( } } + fn set_ssl_verifier(&mut self, _verifier: ::net::ContextVerifier) { + // pass + } } ) diff --git a/src/net.rs b/src/net.rs index e5cfb121..792d0113 100644 --- a/src/net.rs +++ b/src/net.rs @@ -70,6 +70,9 @@ pub trait NetworkConnector { type Stream: Into>; /// Connect to a remote address. fn connect(&mut self, host: &str, port: u16, scheme: &str) -> ::Result; + /// Sets the given `ContextVerifier` to be used when verifying the SSL context + /// on the establishment of a new connection. + fn set_ssl_verifier(&mut self, verifier: ContextVerifier); } impl From for Box { @@ -344,12 +347,15 @@ impl NetworkConnector for HttpConnector { } })) } + fn set_ssl_verifier(&mut self, verifier: ContextVerifier) { + self.0 = Some(verifier); + } } #[cfg(test)] mod tests { use mock::MockStream; - use super::NetworkStream; + use super::{NetworkStream, HttpConnector, NetworkConnector}; #[test] fn test_downcast_box_stream() { @@ -371,4 +377,12 @@ mod tests { } + #[test] + fn test_http_connector_set_ssl_verifier() { + let mut connector = HttpConnector(None); + + connector.set_ssl_verifier(Box::new(|_| {})); + + assert!(connector.0.is_some()); + } }