Skip to content

Commit

Permalink
feat(awc): split connector config with connect config, allow to confi…
Browse files Browse the repository at this point in the history
…gure connect config per request
  • Loading branch information
joelwurtz committed Dec 9, 2024
1 parent d151822 commit 9c96b24
Show file tree
Hide file tree
Showing 11 changed files with 262 additions and 59 deletions.
100 changes: 91 additions & 9 deletions awc/src/client/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,122 @@ use std::{net::IpAddr, time::Duration};
const DEFAULT_H2_CONN_WINDOW: u32 = 1024 * 1024 * 2; // 2MB
const DEFAULT_H2_STREAM_WINDOW: u32 = 1024 * 1024; // 1MB

/// Connector configuration
#[derive(Clone)]
pub(crate) struct ConnectorConfig {
/// Connect configuration
#[derive(Clone, Hash, Eq, PartialEq)]
pub struct ConnectConfig {
pub(crate) timeout: Duration,
pub(crate) handshake_timeout: Duration,
pub(crate) conn_lifetime: Duration,
pub(crate) conn_keep_alive: Duration,
pub(crate) disconnect_timeout: Option<Duration>,
pub(crate) limit: usize,
pub(crate) conn_window_size: u32,
pub(crate) stream_window_size: u32,
pub(crate) local_address: Option<IpAddr>,
}

impl Default for ConnectorConfig {
/// Connector configuration
#[derive(Clone)]
pub struct ConnectorConfig {
pub(crate) default_connect_config: ConnectConfig,
pub(crate) disconnect_timeout: Option<Duration>,
pub(crate) limit: usize,
}

impl Default for ConnectConfig {
fn default() -> Self {
Self {
timeout: Duration::from_secs(5),
handshake_timeout: Duration::from_secs(5),
conn_lifetime: Duration::from_secs(75),
conn_keep_alive: Duration::from_secs(15),
disconnect_timeout: Some(Duration::from_millis(3000)),
limit: 100,
conn_window_size: DEFAULT_H2_CONN_WINDOW,
stream_window_size: DEFAULT_H2_STREAM_WINDOW,
local_address: None,
}
}
}

impl Default for ConnectorConfig {
fn default() -> Self {
Self {
default_connect_config: ConnectConfig::default(),
disconnect_timeout: Some(Duration::from_millis(3000)),
limit: 100,
}
}
}

impl ConnectorConfig {
pub(crate) fn no_disconnect_timeout(&self) -> Self {
pub fn no_disconnect_timeout(&self) -> Self {
let mut res = self.clone();
res.disconnect_timeout = None;
res
}
}

impl ConnectConfig {
/// Sets TCP connection timeout.
///
/// This is the max time allowed to connect to remote host, including DNS name resolution.
///
/// By default, the timeout is 5 seconds.
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = timeout;
self
}

/// Sets TLS handshake timeout.
///
/// This is the max time allowed to perform the TLS handshake with remote host after TCP
/// connection is established.
///
/// By default, the timeout is 5 seconds.
pub fn handshake_timeout(mut self, timeout: Duration) -> Self {
self.handshake_timeout = timeout;
self
}

/// Sets the initial window size (in bytes) for HTTP/2 stream-level flow control for received
/// data.
///
/// The default value is 65,535 and is good for APIs, but not for big objects.
pub fn initial_window_size(mut self, size: u32) -> Self {
self.stream_window_size = size;
self
}

/// Sets the initial window size (in bytes) for HTTP/2 connection-level flow control for
/// received data.
///
/// The default value is 65,535 and is good for APIs, but not for big objects.
pub fn initial_connection_window_size(mut self, size: u32) -> Self {
self.conn_window_size = size;
self
}

/// Set keep-alive period for opened connection.
///
/// Keep-alive period is the period between connection usage. If
/// the delay between repeated usages of the same connection
/// exceeds this period, the connection is closed.
/// Default keep-alive period is 15 seconds.
pub fn conn_keep_alive(mut self, dur: Duration) -> Self {
self.conn_keep_alive = dur;
self
}

/// Set max lifetime period for connection.
///
/// Connection lifetime is max lifetime of any opened connection
/// until it is closed regardless of keep-alive period.
/// Default lifetime period is 75 seconds.
pub fn conn_lifetime(mut self, dur: Duration) -> Self {
self.conn_lifetime = dur;
self
}

/// Set local IP Address the connector would use for establishing connection.
pub fn local_address(mut self, addr: IpAddr) -> Self {
self.local_address = Some(addr);
self
}
}
39 changes: 22 additions & 17 deletions awc/src/client/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ where
///
/// By default, the timeout is 5 seconds.
pub fn timeout(mut self, timeout: Duration) -> Self {
self.config.timeout = timeout;
self.config.default_connect_config.timeout = timeout;
self
}

Expand All @@ -293,7 +293,7 @@ where
///
/// By default, the timeout is 5 seconds.
pub fn handshake_timeout(mut self, timeout: Duration) -> Self {
self.config.handshake_timeout = timeout;
self.config.default_connect_config.handshake_timeout = timeout;
self
}

Expand Down Expand Up @@ -387,7 +387,7 @@ where
///
/// The default value is 65,535 and is good for APIs, but not for big objects.
pub fn initial_window_size(mut self, size: u32) -> Self {
self.config.stream_window_size = size;
self.config.default_connect_config.stream_window_size = size;
self
}

Expand All @@ -396,7 +396,7 @@ where
///
/// The default value is 65,535 and is good for APIs, but not for big objects.
pub fn initial_connection_window_size(mut self, size: u32) -> Self {
self.config.conn_window_size = size;
self.config.default_connect_config.conn_window_size = size;
self
}

Expand All @@ -422,7 +422,7 @@ where
/// exceeds this period, the connection is closed.
/// Default keep-alive period is 15 seconds.
pub fn conn_keep_alive(mut self, dur: Duration) -> Self {
self.config.conn_keep_alive = dur;
self.config.default_connect_config.conn_keep_alive = dur;
self
}

Expand All @@ -432,7 +432,7 @@ where
/// until it is closed regardless of keep-alive period.
/// Default lifetime period is 75 seconds.
pub fn conn_lifetime(mut self, dur: Duration) -> Self {
self.config.conn_lifetime = dur;
self.config.default_connect_config.conn_lifetime = dur;
self
}

Expand All @@ -451,16 +451,16 @@ where

/// Set local IP Address the connector would use for establishing connection.
pub fn local_address(mut self, addr: IpAddr) -> Self {
self.config.local_address = Some(addr);
self.config.default_connect_config.local_address = Some(addr);
self
}

/// Finish configuration process and create connector service.
///
/// The `Connector` builder always concludes by calling `finish()` last in its combinator chain.
pub fn finish(self) -> ConnectorService<S, IO> {
let local_address = self.config.local_address;
let timeout = self.config.timeout;
let local_address = self.config.default_connect_config.local_address;
let timeout = self.config.default_connect_config.timeout;

let tcp_service_inner =
TcpConnectorInnerService::new(self.connector, timeout, local_address);
Expand Down Expand Up @@ -523,7 +523,7 @@ where
}
}

let handshake_timeout = self.config.handshake_timeout;
let handshake_timeout = self.config.default_connect_config.handshake_timeout;

let tls_service = TlsConnectorService {
tcp_service: tcp_service_inner,
Expand Down Expand Up @@ -557,7 +557,7 @@ where
}
}

let handshake_timeout = self.config.handshake_timeout;
let handshake_timeout = self.config.default_connect_config.handshake_timeout;

let tls_service = TlsConnectorService {
tcp_service: tcp_service_inner,
Expand Down Expand Up @@ -596,7 +596,7 @@ where
}
}

let handshake_timeout = self.config.handshake_timeout;
let handshake_timeout = self.config.default_connect_config.handshake_timeout;

let tls_service = TlsConnectorService {
tcp_service: tcp_service_inner,
Expand Down Expand Up @@ -630,7 +630,7 @@ where
}
}

let handshake_timeout = self.config.handshake_timeout;
let handshake_timeout = self.config.default_connect_config.handshake_timeout;

let tls_service = TlsConnectorService {
tcp_service: tcp_service_inner,
Expand Down Expand Up @@ -667,7 +667,7 @@ where
}
}

let handshake_timeout = self.config.handshake_timeout;
let handshake_timeout = self.config.default_connect_config.handshake_timeout;

let tls_service = TlsConnectorService {
tcp_service: tcp_service_inner,
Expand Down Expand Up @@ -701,7 +701,7 @@ where
}
}

let handshake_timeout = self.config.handshake_timeout;
let handshake_timeout = self.config.default_connect_config.handshake_timeout;

let tls_service = TlsConnectorService {
tcp_service: tcp_service_inner,
Expand Down Expand Up @@ -824,9 +824,13 @@ where
}

fn call(&self, req: Connect) -> Self::Future {
let timeout = req
.config
.clone()
.map(|c| c.handshake_timeout)
.unwrap_or(self.timeout);
let fut = self.tcp_service.call(req);
let tls_service = self.tls_service.clone();
let timeout = self.timeout;

TlsConnectorFuture::TcpConnect {
fut,
Expand Down Expand Up @@ -935,6 +939,7 @@ where
actix_service::forward_ready!(service);

fn call(&self, req: Connect) -> Self::Future {
let timeout = req.config.map(|c| c.timeout).unwrap_or(self.timeout);
let mut req = ConnectInfo::new(HostnameWithSni::ForTcp(
req.hostname,
req.port,
Expand All @@ -949,7 +954,7 @@ where

TcpConnectorInnerFuture {
fut: self.service.call(req),
timeout: sleep(self.timeout),
timeout: sleep(timeout),
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions awc/src/client/h2proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use http::{
use log::trace;

use super::{
config::ConnectorConfig,
connection::{ConnectionIo, H2Connection},
error::SendRequestError,
};
Expand Down Expand Up @@ -186,12 +185,13 @@ where

pub(crate) fn handshake<Io: ConnectionIo>(
io: Io,
config: &ConnectorConfig,
stream_window_size: u32,
conn_window_size: u32,
) -> impl Future<Output = Result<(SendRequest<Bytes>, Connection<Io, Bytes>), h2::Error>> {
let mut builder = Builder::new();
builder
.initial_window_size(config.stream_window_size)
.initial_connection_window_size(config.conn_window_size)
.initial_window_size(stream_window_size)
.initial_connection_window_size(conn_window_size)
.enable_push(false);
builder.handshake(io)
}
2 changes: 2 additions & 0 deletions awc/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod h2proto;
mod pool;

pub use self::{
config::ConnectConfig,
connection::{Connection, ConnectionIo},
connector::{Connector, ConnectorService, HostnameWithSni},
error::{ConnectError, FreezeRequestError, InvalidUrl, SendRequestError},
Expand Down Expand Up @@ -49,6 +50,7 @@ pub struct Connect {
pub port: u16,
pub tls: bool,
pub addr: Option<std::net::SocketAddr>,
pub config: Option<Rc<ConnectConfig>>,
}

/// An asynchronous HTTP and WebSocket client.
Expand Down
Loading

0 comments on commit 9c96b24

Please sign in to comment.