Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,28 @@ impl HttpClientBuilder {
self
}

/// Set a mapping of host rule
///
/// Entries in the given map will be used first before using the default host
/// rules for host+port pairs.
///
/// # Examples
///
/// ```
/// use isahc::{config::HostRuleMap, prelude::*, HttpClient};
///
/// let client = HttpClient::builder()
/// .host_rule(HostRuleMap::new()
/// // Send requests for example.org on port 80 to github.com.
/// .add("example.org", 80, "github.com"))
/// .build()?;
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// ```
pub fn host_rule(mut self, map: HostRuleMap) -> Self {
self.client_config.host_rule = Some(map);
self
}

/// Add a default header to be passed with every request.
///
/// If a default header value is already defined for the given key, then a
Expand Down
6 changes: 6 additions & 0 deletions src/config/client.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{
dns::{DnsCache, ResolveMap},
host_rule::HostRuleMap,
request::SetOpt,
};
use std::time::Duration;
Expand All @@ -10,6 +11,7 @@ pub(crate) struct ClientConfig {
pub(crate) close_connections: bool,
pub(crate) dns_cache: Option<DnsCache>,
pub(crate) dns_resolve: Option<ResolveMap>,
pub(crate) host_rule: Option<HostRuleMap>,
}

impl SetOpt for ClientConfig {
Expand All @@ -26,6 +28,10 @@ impl SetOpt for ClientConfig {
map.set_opt(easy)?;
}

if let Some(map) = self.host_rule.as_ref() {
map.set_opt(easy)?;
}

easy.forbid_reuse(self.close_connections)
}
}
39 changes: 39 additions & 0 deletions src/config/host_rule.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//! Configuration of host rule.
use super::SetOpt;

/// A mapping of host and port pairs to specified host
///
/// Entries added to this map can be used to override how host is resolved for a
/// request and use specific host instead of using the default name
/// resolver.
#[derive(Clone, Debug, Default)]
pub struct HostRuleMap(Vec<String>);

impl HostRuleMap {
/// Create a new empty rule map.
pub const fn new() -> Self {
HostRuleMap(Vec::new())
}

/// Add a host mapping for a given host and port pair.
pub fn add<H>(mut self, host: H, port: u16, connect_to_host: H) -> Self
where
H: AsRef<str>,
{
self.0
.push(format!("{}:{}:{}", host.as_ref(), port, connect_to_host.as_ref()));
self
}
}

impl SetOpt for HostRuleMap {
fn set_opt<H>(&self, easy: &mut curl::easy::Easy2<H>) -> Result<(), curl::Error> {
let mut list = curl::easy::List::new();

for entry in self.0.iter() {
list.append(entry)?;
}

easy.connect_to(list)
}
}
2 changes: 2 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ pub(crate) mod client;
pub(crate) mod dial;
pub(crate) mod dns;
pub(crate) mod proxy;
pub(crate) mod host_rule;
pub(crate) mod redirect;
pub(crate) mod request;
pub(crate) mod ssl;

pub use dial::{Dialer, DialerParseError};
pub use dns::{DnsCache, ResolveMap};
pub use host_rule::HostRuleMap;
pub use redirect::RedirectPolicy;
pub use ssl::{CaCertificate, ClientCertificate, PrivateKey, SslOption};

Expand Down