Skip to content

Commit c7b0c06

Browse files
committed
feat(awc): split connector config with connect config, allow to configure connect config per request
1 parent d151822 commit c7b0c06

File tree

11 files changed

+261
-57
lines changed

11 files changed

+261
-57
lines changed

awc/src/client/config.rs

Lines changed: 91 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,122 @@ use std::{net::IpAddr, time::Duration};
33
const DEFAULT_H2_CONN_WINDOW: u32 = 1024 * 1024 * 2; // 2MB
44
const DEFAULT_H2_STREAM_WINDOW: u32 = 1024 * 1024; // 1MB
55

6-
/// Connector configuration
7-
#[derive(Clone)]
8-
pub(crate) struct ConnectorConfig {
6+
/// Connect configuration
7+
#[derive(Clone, Hash, Eq, PartialEq)]
8+
pub struct ConnectConfig {
99
pub(crate) timeout: Duration,
1010
pub(crate) handshake_timeout: Duration,
1111
pub(crate) conn_lifetime: Duration,
1212
pub(crate) conn_keep_alive: Duration,
13-
pub(crate) disconnect_timeout: Option<Duration>,
14-
pub(crate) limit: usize,
1513
pub(crate) conn_window_size: u32,
1614
pub(crate) stream_window_size: u32,
1715
pub(crate) local_address: Option<IpAddr>,
1816
}
1917

20-
impl Default for ConnectorConfig {
18+
/// Connector configuration
19+
#[derive(Clone)]
20+
pub struct ConnectorConfig {
21+
pub(crate) default_connect_config: ConnectConfig,
22+
pub(crate) disconnect_timeout: Option<Duration>,
23+
pub(crate) limit: usize,
24+
}
25+
26+
impl Default for ConnectConfig {
2127
fn default() -> Self {
2228
Self {
2329
timeout: Duration::from_secs(5),
2430
handshake_timeout: Duration::from_secs(5),
2531
conn_lifetime: Duration::from_secs(75),
2632
conn_keep_alive: Duration::from_secs(15),
27-
disconnect_timeout: Some(Duration::from_millis(3000)),
28-
limit: 100,
2933
conn_window_size: DEFAULT_H2_CONN_WINDOW,
3034
stream_window_size: DEFAULT_H2_STREAM_WINDOW,
3135
local_address: None,
3236
}
3337
}
3438
}
3539

40+
impl Default for ConnectorConfig {
41+
fn default() -> Self {
42+
Self {
43+
default_connect_config: ConnectConfig::default(),
44+
disconnect_timeout: Some(Duration::from_millis(3000)),
45+
limit: 100,
46+
}
47+
}
48+
}
49+
3650
impl ConnectorConfig {
37-
pub(crate) fn no_disconnect_timeout(&self) -> Self {
51+
pub fn no_disconnect_timeout(&self) -> Self {
3852
let mut res = self.clone();
3953
res.disconnect_timeout = None;
4054
res
4155
}
4256
}
57+
58+
impl ConnectConfig {
59+
/// Sets TCP connection timeout.
60+
///
61+
/// This is the max time allowed to connect to remote host, including DNS name resolution.
62+
///
63+
/// By default, the timeout is 5 seconds.
64+
pub fn timeout(mut self, timeout: Duration) -> Self {
65+
self.timeout = timeout;
66+
self
67+
}
68+
69+
/// Sets TLS handshake timeout.
70+
///
71+
/// This is the max time allowed to perform the TLS handshake with remote host after TCP
72+
/// connection is established.
73+
///
74+
/// By default, the timeout is 5 seconds.
75+
pub fn handshake_timeout(mut self, timeout: Duration) -> Self {
76+
self.handshake_timeout = timeout;
77+
self
78+
}
79+
80+
/// Sets the initial window size (in bytes) for HTTP/2 stream-level flow control for received
81+
/// data.
82+
///
83+
/// The default value is 65,535 and is good for APIs, but not for big objects.
84+
pub fn initial_window_size(mut self, size: u32) -> Self {
85+
self.stream_window_size = size;
86+
self
87+
}
88+
89+
/// Sets the initial window size (in bytes) for HTTP/2 connection-level flow control for
90+
/// received data.
91+
///
92+
/// The default value is 65,535 and is good for APIs, but not for big objects.
93+
pub fn initial_connection_window_size(mut self, size: u32) -> Self {
94+
self.conn_window_size = size;
95+
self
96+
}
97+
98+
/// Set keep-alive period for opened connection.
99+
///
100+
/// Keep-alive period is the period between connection usage. If
101+
/// the delay between repeated usages of the same connection
102+
/// exceeds this period, the connection is closed.
103+
/// Default keep-alive period is 15 seconds.
104+
pub fn conn_keep_alive(mut self, dur: Duration) -> Self {
105+
self.conn_keep_alive = dur;
106+
self
107+
}
108+
109+
/// Set max lifetime period for connection.
110+
///
111+
/// Connection lifetime is max lifetime of any opened connection
112+
/// until it is closed regardless of keep-alive period.
113+
/// Default lifetime period is 75 seconds.
114+
pub fn conn_lifetime(mut self, dur: Duration) -> Self {
115+
self.conn_lifetime = dur;
116+
self
117+
}
118+
119+
/// Set local IP Address the connector would use for establishing connection.
120+
pub fn local_address(mut self, addr: IpAddr) -> Self {
121+
self.local_address = Some(addr);
122+
self
123+
}
124+
}

awc/src/client/connector.rs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ where
282282
///
283283
/// By default, the timeout is 5 seconds.
284284
pub fn timeout(mut self, timeout: Duration) -> Self {
285-
self.config.timeout = timeout;
285+
self.config.default_connect_config.timeout = timeout;
286286
self
287287
}
288288

@@ -293,7 +293,7 @@ where
293293
///
294294
/// By default, the timeout is 5 seconds.
295295
pub fn handshake_timeout(mut self, timeout: Duration) -> Self {
296-
self.config.handshake_timeout = timeout;
296+
self.config.default_connect_config.handshake_timeout = timeout;
297297
self
298298
}
299299

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

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

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

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

@@ -451,16 +451,16 @@ where
451451

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

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

465465
let tcp_service_inner =
466466
TcpConnectorInnerService::new(self.connector, timeout, local_address);
@@ -523,7 +523,7 @@ where
523523
}
524524
}
525525

526-
let handshake_timeout = self.config.handshake_timeout;
526+
let handshake_timeout = self.config.default_connect_config.handshake_timeout;
527527

528528
let tls_service = TlsConnectorService {
529529
tcp_service: tcp_service_inner,
@@ -557,7 +557,7 @@ where
557557
}
558558
}
559559

560-
let handshake_timeout = self.config.handshake_timeout;
560+
let handshake_timeout = self.config.default_connect_config.handshake_timeout;
561561

562562
let tls_service = TlsConnectorService {
563563
tcp_service: tcp_service_inner,
@@ -596,7 +596,7 @@ where
596596
}
597597
}
598598

599-
let handshake_timeout = self.config.handshake_timeout;
599+
let handshake_timeout = self.config.default_connect_config.handshake_timeout;
600600

601601
let tls_service = TlsConnectorService {
602602
tcp_service: tcp_service_inner,
@@ -630,7 +630,7 @@ where
630630
}
631631
}
632632

633-
let handshake_timeout = self.config.handshake_timeout;
633+
let handshake_timeout = self.config.default_connect_config.handshake_timeout;
634634

635635
let tls_service = TlsConnectorService {
636636
tcp_service: tcp_service_inner,
@@ -667,7 +667,7 @@ where
667667
}
668668
}
669669

670-
let handshake_timeout = self.config.handshake_timeout;
670+
let handshake_timeout = self.config.default_connect_config.handshake_timeout;
671671

672672
let tls_service = TlsConnectorService {
673673
tcp_service: tcp_service_inner,
@@ -701,7 +701,7 @@ where
701701
}
702702
}
703703

704-
let handshake_timeout = self.config.handshake_timeout;
704+
let handshake_timeout = self.config.default_connect_config.handshake_timeout;
705705

706706
let tls_service = TlsConnectorService {
707707
tcp_service: tcp_service_inner,
@@ -824,9 +824,13 @@ where
824824
}
825825

826826
fn call(&self, req: Connect) -> Self::Future {
827+
let timeout = req
828+
.config
829+
.clone()
830+
.map(|c| c.handshake_timeout)
831+
.unwrap_or(self.timeout);
827832
let fut = self.tcp_service.call(req);
828833
let tls_service = self.tls_service.clone();
829-
let timeout = self.timeout;
830834

831835
TlsConnectorFuture::TcpConnect {
832836
fut,
@@ -935,6 +939,7 @@ where
935939
actix_service::forward_ready!(service);
936940

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

950955
TcpConnectorInnerFuture {
951956
fut: self.service.call(req),
952-
timeout: sleep(self.timeout),
957+
timeout: sleep(timeout),
953958
}
954959
}
955960
}

awc/src/client/h2proto.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use http::{
1919
use log::trace;
2020

2121
use super::{
22-
config::ConnectorConfig,
2322
connection::{ConnectionIo, H2Connection},
2423
error::SendRequestError,
2524
};
@@ -186,12 +185,13 @@ where
186185

187186
pub(crate) fn handshake<Io: ConnectionIo>(
188187
io: Io,
189-
config: &ConnectorConfig,
188+
stream_window_size: u32,
189+
conn_window_size: u32,
190190
) -> impl Future<Output = Result<(SendRequest<Bytes>, Connection<Io, Bytes>), h2::Error>> {
191191
let mut builder = Builder::new();
192192
builder
193-
.initial_window_size(config.stream_window_size)
194-
.initial_connection_window_size(config.conn_window_size)
193+
.initial_window_size(stream_window_size)
194+
.initial_connection_window_size(conn_window_size)
195195
.enable_push(false);
196196
builder.handshake(io)
197197
}

awc/src/client/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ mod h2proto;
2020
mod pool;
2121

2222
pub use self::{
23+
config::ConnectConfig,
2324
connection::{Connection, ConnectionIo},
2425
connector::{Connector, ConnectorService, HostnameWithSni},
2526
error::{ConnectError, FreezeRequestError, InvalidUrl, SendRequestError},
@@ -49,6 +50,7 @@ pub struct Connect {
4950
pub port: u16,
5051
pub tls: bool,
5152
pub addr: Option<std::net::SocketAddr>,
53+
pub config: Option<Rc<ConnectConfig>>,
5254
}
5355

5456
/// An asynchronous HTTP and WebSocket client.

0 commit comments

Comments
 (0)