add H2 window size configuration and max_http_version to awc::ClientBuilder

This commit is contained in:
Maksym Vorobiov 2020-03-04 17:28:07 +02:00
parent eab0a292e9
commit ebef0fad26
2 changed files with 46 additions and 19 deletions

View File

@ -1,5 +1,11 @@
# Changes # Changes
## [NEXT]
* ClientBuilder accepts initial_window_size and initial_connection_window_size HTTP2 configuration
* ClientBuilder allowing to set max_http_version to limit HTTP version to be used
## [1.0.1] - 2019-12-15 ## [1.0.1] - 2019-12-15
* Fix compilation with default features off * Fix compilation with default features off

View File

@ -4,11 +4,11 @@ use std::fmt;
use std::rc::Rc; use std::rc::Rc;
use std::time::Duration; use std::time::Duration;
use actix_http::client::{Connect, ConnectError, Connection, Connector}; use actix_http::client::{Connect as HttpConnect, ConnectError, Connection, Connector};
use actix_http::http::{header, Error as HttpError, HeaderMap, HeaderName}; use actix_http::http::{header, Error as HttpError, HeaderMap, HeaderName};
use actix_service::Service; use actix_service::Service;
use crate::connect::ConnectorWrapper; use crate::connect::{ConnectorWrapper, Connect};
use crate::{Client, ClientConfig}; use crate::{Client, ClientConfig};
/// An HTTP Client builder /// An HTTP Client builder
@ -16,10 +16,15 @@ use crate::{Client, ClientConfig};
/// This type can be used to construct an instance of `Client` through a /// This type can be used to construct an instance of `Client` through a
/// builder-like pattern. /// builder-like pattern.
pub struct ClientBuilder { pub struct ClientBuilder {
config: ClientConfig,
default_headers: bool, default_headers: bool,
allow_redirects: bool, allow_redirects: bool,
max_redirects: usize, max_redirects: usize,
max_http_version: Option<u8>,
stream_window_size: Option<u32>,
conn_window_size: Option<u32>,
headers: HeaderMap,
timeout: Option<Duration>,
connector: Option<RefCell<Box<dyn Connect>>>,
} }
impl Default for ClientBuilder { impl Default for ClientBuilder {
@ -34,25 +39,24 @@ impl ClientBuilder {
default_headers: true, default_headers: true,
allow_redirects: true, allow_redirects: true,
max_redirects: 10, max_redirects: 10,
config: ClientConfig { headers: HeaderMap::new(),
headers: HeaderMap::new(), timeout: Some(Duration::from_secs(5)),
timeout: Some(Duration::from_secs(5)), connector: None,
connector: RefCell::new(Box::new(ConnectorWrapper( max_http_version: None,
Connector::new().finish(), stream_window_size: None,
))), conn_window_size: None,
},
} }
} }
/// Use custom connector service. /// Use custom connector service.
pub fn connector<T>(mut self, connector: T) -> Self pub fn connector<T>(mut self, connector: T) -> Self
where where
T: Service<Request = Connect, Error = ConnectError> + 'static, T: Service<Request = HttpConnect, Error = ConnectError> + 'static,
T::Response: Connection, T::Response: Connection,
<T::Response as Connection>::Future: 'static, <T::Response as Connection>::Future: 'static,
T::Future: 'static, T::Future: 'static,
{ {
self.config.connector = RefCell::new(Box::new(ConnectorWrapper(connector))); self.connector = Some(RefCell::new(Box::new(ConnectorWrapper(connector))));
self self
} }
@ -61,13 +65,13 @@ impl ClientBuilder {
/// Request timeout is the total time before a response must be received. /// Request timeout is the total time before a response must be received.
/// Default value is 5 seconds. /// Default value is 5 seconds.
pub fn timeout(mut self, timeout: Duration) -> Self { pub fn timeout(mut self, timeout: Duration) -> Self {
self.config.timeout = Some(timeout); self.timeout = Some(timeout);
self self
} }
/// Disable request timeout. /// Disable request timeout.
pub fn disable_timeout(mut self) -> Self { pub fn disable_timeout(mut self) -> Self {
self.config.timeout = None; self.timeout = None;
self self
} }
@ -106,7 +110,7 @@ impl ClientBuilder {
match HeaderName::try_from(key) { match HeaderName::try_from(key) {
Ok(key) => match value.try_into() { Ok(key) => match value.try_into() {
Ok(value) => { Ok(value) => {
self.config.headers.append(key, value); self.headers.append(key, value);
} }
Err(e) => log::error!("Header value error: {:?}", e), Err(e) => log::error!("Header value error: {:?}", e),
}, },
@ -140,7 +144,27 @@ impl ClientBuilder {
/// Finish build process and create `Client` instance. /// Finish build process and create `Client` instance.
pub fn finish(self) -> Client { pub fn finish(self) -> Client {
Client(Rc::new(self.config)) let connector = if self.connector.is_some() {
self.connector.unwrap()
} else {
let mut connector = Connector::new();
if let Some(val) = self.max_http_version {
connector = connector.max_http_version(val)
};
if let Some(val) = self.conn_window_size {
connector = connector.initial_connection_window_size(val)
};
if let Some(val) = self.stream_window_size {
connector = connector.initial_window_size(val)
};
RefCell::new(Box::new(ConnectorWrapper(connector.finish())) as Box<dyn Connect>)
};
let config = ClientConfig {
headers: self.headers,
timeout: self.timeout,
connector,
};
Client(Rc::new(config))
} }
} }
@ -153,7 +177,6 @@ mod tests {
let client = ClientBuilder::new().basic_auth("username", Some("password")); let client = ClientBuilder::new().basic_auth("username", Some("password"));
assert_eq!( assert_eq!(
client client
.config
.headers .headers
.get(header::AUTHORIZATION) .get(header::AUTHORIZATION)
.unwrap() .unwrap()
@ -165,7 +188,6 @@ mod tests {
let client = ClientBuilder::new().basic_auth("username", None); let client = ClientBuilder::new().basic_auth("username", None);
assert_eq!( assert_eq!(
client client
.config
.headers .headers
.get(header::AUTHORIZATION) .get(header::AUTHORIZATION)
.unwrap() .unwrap()
@ -180,7 +202,6 @@ mod tests {
let client = ClientBuilder::new().bearer_auth("someS3cr3tAutht0k3n"); let client = ClientBuilder::new().bearer_auth("someS3cr3tAutht0k3n");
assert_eq!( assert_eq!(
client client
.config
.headers .headers
.get(header::AUTHORIZATION) .get(header::AUTHORIZATION)
.unwrap() .unwrap()