diff --git a/actix-http/src/builder.rs b/actix-http/src/builder.rs index 916083a98..95da8ac62 100644 --- a/actix-http/src/builder.rs +++ b/actix-http/src/builder.rs @@ -7,7 +7,7 @@ use crate::{ body::{BoxBody, MessageBody}, h1::{self, ExpectHandler, H1Service, UpgradeHandler}, service::HttpService, - ConnectCallback, Extensions, KeepAlive, Request, Response, ServiceConfig, + ConnectCallback, Extensions, KeepAlive, Request, Response, ServiceConfigBuilder, }; /// An HTTP service builder. @@ -195,13 +195,13 @@ where S::InitError: fmt::Debug, S::Response: Into>, { - let cfg = ServiceConfig::new( - self.keep_alive, - self.client_request_timeout, - self.client_disconnect_timeout, - self.secure, - self.local_addr, - ); + let cfg = ServiceConfigBuilder::new() + .keep_alive(self.keep_alive) + .client_request_timeout(self.client_request_timeout) + .client_disconnect_timeout(self.client_disconnect_timeout) + .secure(self.secure) + .local_addr(self.local_addr) + .build(); H1Service::with_config(cfg, service.into_factory()) .expect(self.expect) @@ -220,13 +220,13 @@ where B: MessageBody + 'static, { - let cfg = ServiceConfig::new( - self.keep_alive, - self.client_request_timeout, - self.client_disconnect_timeout, - self.secure, - self.local_addr, - ); + let cfg = ServiceConfigBuilder::new() + .keep_alive(self.keep_alive) + .client_request_timeout(self.client_request_timeout) + .client_disconnect_timeout(self.client_disconnect_timeout) + .secure(self.secure) + .local_addr(self.local_addr) + .build(); crate::h2::H2Service::with_config(cfg, service.into_factory()) .on_connect_ext(self.on_connect_ext) @@ -242,13 +242,13 @@ where B: MessageBody + 'static, { - let cfg = ServiceConfig::new( - self.keep_alive, - self.client_request_timeout, - self.client_disconnect_timeout, - self.secure, - self.local_addr, - ); + let cfg = ServiceConfigBuilder::new() + .keep_alive(self.keep_alive) + .client_request_timeout(self.client_request_timeout) + .client_disconnect_timeout(self.client_disconnect_timeout) + .secure(self.secure) + .local_addr(self.local_addr) + .build(); HttpService::with_config(cfg, service.into_factory()) .expect(self.expect) diff --git a/actix-http/src/config.rs b/actix-http/src/config.rs index b3b215da4..840abeaaf 100644 --- a/actix-http/src/config.rs +++ b/actix-http/src/config.rs @@ -1,5 +1,5 @@ use std::{ - net, + net::SocketAddr, rc::Rc, time::{Duration, Instant}, }; @@ -8,6 +8,70 @@ use bytes::BytesMut; use crate::{date::DateService, KeepAlive}; +/// A builder for creating a [`ServiceConfig`] +pub struct ServiceConfigBuilder { + inner: Inner, +} + +impl ServiceConfigBuilder { + /// Creates a new, default, [`ServiceConfigBuilder`] + /// + /// It uses the following default values: + /// + /// - [`KeepAlive::default`] for the connection keep-alive setting + /// - 5 seconds for the client request timeout + /// - 0 seconds for the client shutdown timeout + /// - secure value of `false` + /// - [`None`] for the local address setting + pub fn new() -> Self { + Self::default() + } + + /// Sets the `secure` attribute for this configuration + pub fn secure(mut self, secure: bool) -> Self { + self.inner.secure = secure; + self + } + + /// Sets the local address for this configuration + pub fn local_addr(mut self, local_addr: Option) -> Self { + self.inner.local_addr = local_addr; + self + } + + /// Sets connection keep-alive setting + pub fn keep_alive(mut self, keep_alive: KeepAlive) -> Self { + self.inner.keep_alive = keep_alive; + self + } + + /// Sets the timeout for the client to finish sending the head of its first request + pub fn client_request_timeout(mut self, timeout: Duration) -> Self { + self.inner.client_request_timeout = timeout; + self + } + + /// Sets the timeout for cleanly disconnecting from the client after connection shutdown has + /// started + pub fn client_disconnect_timeout(mut self, timeout: Duration) -> Self { + self.inner.client_disconnect_timeout = timeout; + self + } + + /// Builds a [`ServiceConfig`] from this [`ServiceConfigBuilder`] instance + pub fn build(self) -> ServiceConfig { + ServiceConfig(Rc::new(self.inner)) + } +} + +impl Default for ServiceConfigBuilder { + fn default() -> Self { + Self { + inner: Inner::default(), + } + } +} + /// HTTP service configuration. #[derive(Debug, Clone)] pub struct ServiceConfig(Rc); @@ -18,19 +82,26 @@ struct Inner { client_request_timeout: Duration, client_disconnect_timeout: Duration, secure: bool, - local_addr: Option, + local_addr: Option, date_service: DateService, } +impl Default for Inner { + fn default() -> Self { + Self { + keep_alive: KeepAlive::default(), + client_request_timeout: Duration::from_secs(5), + client_disconnect_timeout: Duration::ZERO, + secure: false, + local_addr: None, + date_service: DateService::new(), + } + } +} + impl Default for ServiceConfig { fn default() -> Self { - Self::new( - KeepAlive::default(), - Duration::from_secs(5), - Duration::ZERO, - false, - None, - ) + Self(Rc::default()) } } @@ -41,7 +112,7 @@ impl ServiceConfig { client_request_timeout: Duration, client_disconnect_timeout: Duration, secure: bool, - local_addr: Option, + local_addr: Option, ) -> ServiceConfig { ServiceConfig(Rc::new(Inner { keep_alive: keep_alive.normalize(), @@ -63,7 +134,7 @@ impl ServiceConfig { /// /// Returns `None` for connections via UDS (Unix Domain Socket). #[inline] - pub fn local_addr(&self) -> Option { + pub fn local_addr(&self) -> Option { self.0.local_addr } diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs index a970056de..ae3713f20 100644 --- a/actix-http/src/lib.rs +++ b/actix-http/src/lib.rs @@ -63,7 +63,7 @@ pub use self::payload::PayloadStream; pub use self::service::TlsAcceptorConfig; pub use self::{ builder::HttpServiceBuilder, - config::ServiceConfig, + config::{ServiceConfig, ServiceConfigBuilder}, error::Error, extensions::Extensions, header::ContentEncoding,