Add ServiceConfigBuilder to facilitate future extensions

Signed-off-by: Thales Fragoso <thales.fragoso@axiros.com>
This commit is contained in:
Thales Fragoso 2025-09-17 17:42:20 -03:00 committed by Yuki Okushi
parent 429ff82a4b
commit 3a3e286b35
3 changed files with 105 additions and 34 deletions

View File

@ -7,7 +7,7 @@ use crate::{
body::{BoxBody, MessageBody}, body::{BoxBody, MessageBody},
h1::{self, ExpectHandler, H1Service, UpgradeHandler}, h1::{self, ExpectHandler, H1Service, UpgradeHandler},
service::HttpService, service::HttpService,
ConnectCallback, Extensions, KeepAlive, Request, Response, ServiceConfig, ConnectCallback, Extensions, KeepAlive, Request, Response, ServiceConfigBuilder,
}; };
/// An HTTP service builder. /// An HTTP service builder.
@ -195,13 +195,13 @@ where
S::InitError: fmt::Debug, S::InitError: fmt::Debug,
S::Response: Into<Response<B>>, S::Response: Into<Response<B>>,
{ {
let cfg = ServiceConfig::new( let cfg = ServiceConfigBuilder::new()
self.keep_alive, .keep_alive(self.keep_alive)
self.client_request_timeout, .client_request_timeout(self.client_request_timeout)
self.client_disconnect_timeout, .client_disconnect_timeout(self.client_disconnect_timeout)
self.secure, .secure(self.secure)
self.local_addr, .local_addr(self.local_addr)
); .build();
H1Service::with_config(cfg, service.into_factory()) H1Service::with_config(cfg, service.into_factory())
.expect(self.expect) .expect(self.expect)
@ -220,13 +220,13 @@ where
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
let cfg = ServiceConfig::new( let cfg = ServiceConfigBuilder::new()
self.keep_alive, .keep_alive(self.keep_alive)
self.client_request_timeout, .client_request_timeout(self.client_request_timeout)
self.client_disconnect_timeout, .client_disconnect_timeout(self.client_disconnect_timeout)
self.secure, .secure(self.secure)
self.local_addr, .local_addr(self.local_addr)
); .build();
crate::h2::H2Service::with_config(cfg, service.into_factory()) crate::h2::H2Service::with_config(cfg, service.into_factory())
.on_connect_ext(self.on_connect_ext) .on_connect_ext(self.on_connect_ext)
@ -242,13 +242,13 @@ where
B: MessageBody + 'static, B: MessageBody + 'static,
{ {
let cfg = ServiceConfig::new( let cfg = ServiceConfigBuilder::new()
self.keep_alive, .keep_alive(self.keep_alive)
self.client_request_timeout, .client_request_timeout(self.client_request_timeout)
self.client_disconnect_timeout, .client_disconnect_timeout(self.client_disconnect_timeout)
self.secure, .secure(self.secure)
self.local_addr, .local_addr(self.local_addr)
); .build();
HttpService::with_config(cfg, service.into_factory()) HttpService::with_config(cfg, service.into_factory())
.expect(self.expect) .expect(self.expect)

View File

@ -1,5 +1,5 @@
use std::{ use std::{
net, net::SocketAddr,
rc::Rc, rc::Rc,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
@ -8,6 +8,70 @@ use bytes::BytesMut;
use crate::{date::DateService, KeepAlive}; 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<SocketAddr>) -> 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. /// HTTP service configuration.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ServiceConfig(Rc<Inner>); pub struct ServiceConfig(Rc<Inner>);
@ -18,19 +82,26 @@ struct Inner {
client_request_timeout: Duration, client_request_timeout: Duration,
client_disconnect_timeout: Duration, client_disconnect_timeout: Duration,
secure: bool, secure: bool,
local_addr: Option<std::net::SocketAddr>, local_addr: Option<SocketAddr>,
date_service: DateService, 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 { impl Default for ServiceConfig {
fn default() -> Self { fn default() -> Self {
Self::new( Self(Rc::default())
KeepAlive::default(),
Duration::from_secs(5),
Duration::ZERO,
false,
None,
)
} }
} }
@ -41,7 +112,7 @@ impl ServiceConfig {
client_request_timeout: Duration, client_request_timeout: Duration,
client_disconnect_timeout: Duration, client_disconnect_timeout: Duration,
secure: bool, secure: bool,
local_addr: Option<net::SocketAddr>, local_addr: Option<SocketAddr>,
) -> ServiceConfig { ) -> ServiceConfig {
ServiceConfig(Rc::new(Inner { ServiceConfig(Rc::new(Inner {
keep_alive: keep_alive.normalize(), keep_alive: keep_alive.normalize(),
@ -63,7 +134,7 @@ impl ServiceConfig {
/// ///
/// Returns `None` for connections via UDS (Unix Domain Socket). /// Returns `None` for connections via UDS (Unix Domain Socket).
#[inline] #[inline]
pub fn local_addr(&self) -> Option<net::SocketAddr> { pub fn local_addr(&self) -> Option<SocketAddr> {
self.0.local_addr self.0.local_addr
} }

View File

@ -63,7 +63,7 @@ pub use self::payload::PayloadStream;
pub use self::service::TlsAcceptorConfig; pub use self::service::TlsAcceptorConfig;
pub use self::{ pub use self::{
builder::HttpServiceBuilder, builder::HttpServiceBuilder,
config::ServiceConfig, config::{ServiceConfig, ServiceConfigBuilder},
error::Error, error::Error,
extensions::Extensions, extensions::Extensions,
header::ContentEncoding, header::ContentEncoding,