Skip to content

Commit

Permalink
Add HttpsConnectorBuilder
Browse files Browse the repository at this point in the history
This gives more control over various rustls features,
as well as ensures that enabling connector features
like http2 can only be done when the appropriate crate
features are enabled.

Adds an hyper-rustls/http2 feature.
  • Loading branch information
g2p committed Feb 11, 2021
1 parent 3f16ac4 commit db41b50
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 17 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ futures-util = { version = "0.3.1", default-features = false }

[features]
default = ["native-tokio"]
http2 = ["hyper/http2"]
webpki-tokio = ["tokio-runtime", "webpki-roots"]
native-tokio = ["tokio-runtime", "rustls-native-certs"]
tokio-runtime = ["hyper/runtime", "ct-logs"]
tokio-runtime = ["hyper/tcp", "ct-logs"]

[[example]]
name = "client"
Expand Down
2 changes: 1 addition & 1 deletion examples/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ async fn run_client() -> io::Result<()> {
hyper_rustls::HttpsConnector::from((http, tls))
}
// Default HTTPS connector.
None => hyper_rustls::HttpsConnector::with_native_roots(),
None => hyper_rustls::HttpsConnectorBuilder::with_native_roots().build(),
};

// Build the hyper client from the HTTPS connector.
Expand Down
59 changes: 46 additions & 13 deletions src/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,18 @@ pub struct HttpsConnector<T> {
tls_config: Arc<ClientConfig>,
}

#[cfg(all(
any(feature = "rustls-native-certs", feature = "webpki-roots"),
feature = "tokio-runtime"
))]
impl HttpsConnector<HttpConnector> {
/// Construct a new `HttpsConnector` using the OS root store
/// A builder that will configure an `HttpsConnector`
///
/// This builder ensures configuration is consistent.
///
/// An alternative way of building an `HttpsConnector`
/// is to use From/Into.
pub struct HttpsConnectorBuilder {
tls_config: ClientConfig,
}

impl HttpsConnectorBuilder {
/// Configure using the OS root store for certificate trust
#[cfg(feature = "rustls-native-certs")]
#[cfg_attr(docsrs, doc(cfg(feature = "rustls-native-certs")))]
pub fn with_native_roots() -> Self {
Expand All @@ -43,27 +49,54 @@ impl HttpsConnector<HttpConnector> {
if config.root_store.is_empty() {
panic!("no CA certificates found");
}
Self::build(config)
Self { tls_config: config }
}

/// Configure using a custom `rustls::RootCertStore` for certificate trust
pub fn with_custom_roots(roots: rustls::RootCertStore) -> Self {
let mut config = ClientConfig::new();
config.root_store = roots;
Self { tls_config: config }
}

/// Construct a new `HttpsConnector` using the `webpki_roots`
/// Configure using `webpki_roots` for certificate trust
#[cfg(feature = "webpki-roots")]
#[cfg_attr(docsrs, doc(cfg(feature = "webpki-roots")))]
pub fn with_webpki_roots() -> Self {
let mut config = ClientConfig::new();
config
.root_store
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
Self::build(config)
Self { tls_config: config }
}

fn build(mut config: ClientConfig) -> Self {
/// Enable HTTP2
/// This advertises http2 support in ALPN
#[cfg(feature = "http2")]
#[cfg_attr(docsrs, doc(cfg(feature = "http2")))]
pub fn enable_http2(mut self) -> Self {
self.tls_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
self
}

/// Enable certificate transparency
#[cfg(feature = "ct-logs")]
pub fn enable_ct_logs(mut self) -> Self {
self.tls_config.ct_logs = Some(&ct_logs::LOGS);
self
}

/// Built an HttpsConnector<HttpConnector>
#[cfg(feature = "tokio-runtime")]
pub fn build(self) -> HttpsConnector<HttpConnector> {
let mut http = HttpConnector::new();
http.enforce_http(false);
self.wrap_connector(http)
}

config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
config.ct_logs = Some(&ct_logs::LOGS);
(http, config).into()
/// Built an HttpsConnector with a custom lower-level connector
pub fn wrap_connector<H>(self, conn: H) -> HttpsConnector<H> {
(conn, self.tls_config).into()
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
//!
//! let mut rt = tokio::runtime::Runtime::new().unwrap();
//! let url = ("https://hyper.rs").parse().unwrap();
//! let https = hyper_rustls::HttpsConnector::with_native_roots();
//! let https = hyper_rustls::HttpsConnectorBuilder::with_native_roots().build();
//!
//! let client: Client<_, hyper::Body> = Client::builder().build(https);
//!
Expand All @@ -27,5 +27,5 @@
mod connector;
mod stream;

pub use crate::connector::HttpsConnector;
pub use crate::connector::{HttpsConnector, HttpsConnectorBuilder};
pub use crate::stream::MaybeHttpsStream;

0 comments on commit db41b50

Please sign in to comment.