Skip to content

Commit

Permalink
review
Browse files Browse the repository at this point in the history
  • Loading branch information
sfackler committed Apr 9, 2024
1 parent 93b06c6 commit f46a93b
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 84 deletions.
107 changes: 79 additions & 28 deletions src/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use pki_types::ServerName;
use tokio_rustls::TlsConnector;
use tower_service::Service;

use crate::server_name_resolver::ResolveServerName;
use crate::stream::MaybeHttpsStream;

pub(crate) mod builder;
Expand All @@ -25,7 +24,7 @@ pub struct HttpsConnector<T> {
force_https: bool,
http: T,
tls_config: Arc<rustls::ClientConfig>,
server_name_resolver: Option<Arc<dyn ResolveServerName + Sync + Send>>,
server_name_resolver: Arc<dyn ResolveServerName + Sync + Send>,
}

impl<T> HttpsConnector<T> {
Expand Down Expand Up @@ -91,31 +90,10 @@ where
};

let cfg = self.tls_config.clone();
let hostname = match &self.server_name_resolver {
Some(server_name_resolver) => match server_name_resolver.resolve(&dst) {
Ok(hostname) => hostname,
Err(e) => {
return Box::pin(async move { Err(e) });
}
},
None => {
let mut hostname = dst.host().unwrap_or_default();

// Remove square brackets around IPv6 address.
if let Some(trimmed) = hostname
.strip_prefix('[')
.and_then(|h| h.strip_suffix(']'))
{
hostname = trimmed;
}

match ServerName::try_from(hostname) {
Ok(dns_name) => dns_name.to_owned(),
Err(_) => {
let err = io::Error::new(io::ErrorKind::Other, "invalid dnsname");
return Box::pin(async move { Err(Box::new(err).into()) });
}
}
let hostname = match self.server_name_resolver.resolve(&dst) {
Ok(hostname) => hostname,
Err(e) => {
return Box::pin(async move { Err(e) });
}
};

Expand Down Expand Up @@ -143,7 +121,7 @@ where
force_https: false,
http,
tls_config: cfg.into(),
server_name_resolver: None,
server_name_resolver: Arc::new(DefaultServerNameResolver::new()),
}
}
}
Expand All @@ -155,3 +133,76 @@ impl<T> fmt::Debug for HttpsConnector<T> {
.finish()
}
}

/// The default server name resolver, which uses the hostname in the URI.
#[derive(Default)]
pub struct DefaultServerNameResolver(());

impl DefaultServerNameResolver {
/// Creates a new resolver.
pub fn new() -> Self {
Self::default()
}
}

impl ResolveServerName for DefaultServerNameResolver {
fn resolve(
&self,
uri: &Uri,
) -> Result<ServerName<'static>, Box<dyn std::error::Error + Sync + Send>> {
let mut hostname = uri.host().unwrap_or_default();

// Remove square brackets around IPv6 address.
if let Some(trimmed) = hostname
.strip_prefix('[')
.and_then(|h| h.strip_suffix(']'))
{
hostname = trimmed;
}

ServerName::try_from(hostname.to_string()).map_err(|e| Box::new(e) as _)
}
}

/// A server name resolver which always returns the same fixed name.
pub struct FixedServerNameResolver {
name: ServerName<'static>,
}

impl FixedServerNameResolver {
/// Creates a new resolver returning the specified name.
pub fn new(name: ServerName<'static>) -> Self {
Self { name }
}
}

impl ResolveServerName for FixedServerNameResolver {
fn resolve(
&self,
_: &Uri,
) -> Result<ServerName<'static>, Box<dyn std::error::Error + Sync + Send>> {
Ok(self.name.clone())
}
}

impl<F, E> ResolveServerName for F
where
F: Fn(&Uri) -> Result<ServerName<'static>, E>,
E: Into<Box<dyn std::error::Error + Sync + Send>>,
{
fn resolve(
&self,
uri: &Uri,
) -> Result<ServerName<'static>, Box<dyn std::error::Error + Sync + Send>> {
self(uri).map_err(Into::into)
}
}

/// A trait implemented by types that can resolve a [`ServerName`] for a request.
pub trait ResolveServerName {
/// Maps a [`Uri`] into a [`ServerName`].
fn resolve(
&self,
uri: &Uri,
) -> Result<ServerName<'static>, Box<dyn std::error::Error + Sync + Send>>;
}
31 changes: 22 additions & 9 deletions src/connector/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use hyper_util::client::legacy::connect::HttpConnector;
use rustls::crypto::CryptoProvider;
use rustls::ClientConfig;

use super::HttpsConnector;
use super::{DefaultServerNameResolver, HttpsConnector, ResolveServerName};
#[cfg(any(feature = "rustls-native-certs", feature = "webpki-roots"))]
use crate::config::ConfigBuilderExt;
use crate::server_name_resolver::{FixedServerNameResolver, ResolveServerName};
use pki_types::ServerName;

/// A builder for an [`HttpsConnector`]
///
Expand Down Expand Up @@ -189,7 +189,9 @@ impl WantsProtocols1 {
force_https: self.https_only,
http: conn,
tls_config: std::sync::Arc::new(self.tls_config),
server_name_resolver: self.server_name_resolver,
server_name_resolver: self
.server_name_resolver
.unwrap_or_else(|| Arc::new(DefaultServerNameResolver::new())),
}
}

Expand Down Expand Up @@ -248,10 +250,10 @@ impl ConnectorBuilder<WantsProtocols1> {
///
/// If this method is called, hyper-rustls will instead use this resolver
/// to compute the value used to verify the server certificate.
pub fn with_server_name_resolver<T>(mut self, resolver: T) -> Self
where
T: ResolveServerName + 'static + Sync + Send,
{
pub fn with_server_name_resolver(
mut self,
resolver: impl ResolveServerName + 'static + Sync + Send,
) -> Self {
self.0.server_name_resolver = Some(Arc::new(resolver));
self
}
Expand All @@ -265,8 +267,19 @@ impl ConnectorBuilder<WantsProtocols1> {
/// If this method is called, hyper-rustls will instead verify that server
/// certificate contains `override_server_name`. Domain name included in
/// the URL will not affect certificate validation.
pub fn with_server_name(self, override_server_name: String) -> Self {
self.with_server_name_resolver(FixedServerNameResolver::new(override_server_name))
#[deprecated(since = "0.27.1", note = "use Self::with_server_name_resolver instead")]
pub fn with_server_name(self, mut override_server_name: String) -> Self {
// remove square brackets around IPv6 address.
if let Some(trimmed) = override_server_name
.strip_prefix('[')
.and_then(|s| s.strip_suffix(']'))
{
override_server_name = trimmed.to_string();
}

self.with_server_name_resolver(move |_: &_| {
ServerName::try_from(override_server_name.clone())
})
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@

mod config;
mod connector;
mod server_name_resolver;
mod stream;

#[cfg(feature = "logging")]
Expand All @@ -56,8 +55,9 @@ mod log {

pub use crate::config::ConfigBuilderExt;
pub use crate::connector::builder::ConnectorBuilder as HttpsConnectorBuilder;
pub use crate::connector::HttpsConnector;
pub use crate::server_name_resolver::ResolveServerName;
pub use crate::connector::{
DefaultServerNameResolver, FixedServerNameResolver, HttpsConnector, ResolveServerName,
};
pub use crate::stream::MaybeHttpsStream;

/// The various states of the [`HttpsConnectorBuilder`]
Expand Down
44 changes: 0 additions & 44 deletions src/server_name_resolver.rs

This file was deleted.

0 comments on commit f46a93b

Please sign in to comment.