use std::{error::Error, fmt, marker::PhantomData};
use crate::http::body::MessageBody;
use crate::http::config::{KeepAlive, ServiceConfig};
use crate::http::error::{H2Error, ResponseError};
use crate::http::h1::{self, H1Service};
use crate::http::h2::{self, H2Service};
use crate::http::{request::Request, response::Response, service::HttpService};
use crate::service::{IntoServiceFactory, ServiceFactory};
use crate::{io::Filter, time::Seconds};
pub struct HttpServiceBuilder<
F,
S,
C1 = h1::DefaultControlService,
C2 = h2::DefaultControlService,
> {
config: ServiceConfig,
h1_control: C1,
h2_control: C2,
_t: PhantomData<(F, S)>,
}
impl<F, S> HttpServiceBuilder<F, S, h1::DefaultControlService, h2::DefaultControlService> {
pub fn new() -> Self {
HttpServiceBuilder::with_config(ServiceConfig::default())
}
#[doc(hidden)]
pub fn with_config(config: ServiceConfig) -> Self {
HttpServiceBuilder {
config,
h1_control: h1::DefaultControlService,
h2_control: h2::DefaultControlService,
_t: PhantomData,
}
}
}
impl<F, S, C1, C2> HttpServiceBuilder<F, S, C1, C2>
where
F: Filter,
S: ServiceFactory<Request> + 'static,
S::Error: ResponseError,
S::InitError: fmt::Debug,
C1: ServiceFactory<h1::Control<F, S::Error>, Response = h1::ControlAck>,
C1::Error: Error,
C1::InitError: fmt::Debug,
C2: ServiceFactory<h2::Control<H2Error>, Response = h2::ControlAck>,
C2::Error: Error,
C2::InitError: fmt::Debug,
{
pub fn keep_alive<W: Into<KeepAlive>>(mut self, val: W) -> Self {
self.config.keepalive(val);
self
}
pub fn client_timeout(mut self, timeout: Seconds) -> Self {
self.config.client_timeout(timeout);
self
}
pub fn disconnect_timeout(mut self, timeout: Seconds) -> Self {
self.config.disconnect_timeout(timeout);
self
}
pub fn ssl_handshake_timeout(mut self, timeout: Seconds) -> Self {
self.config.ssl_handshake_timeout(timeout);
self
}
pub fn headers_read_rate(
mut self,
timeout: Seconds,
max_timeout: Seconds,
rate: u16,
) -> Self {
self.config.headers_read_rate(timeout, max_timeout, rate);
self
}
pub fn payload_read_rate(
mut self,
timeout: Seconds,
max_timeout: Seconds,
rate: u16,
) -> Self {
self.config.payload_read_rate(timeout, max_timeout, rate);
self
}
pub fn h1_control<CF, CT>(self, control: CF) -> HttpServiceBuilder<F, S, CT, C2>
where
CF: IntoServiceFactory<CT, h1::Control<F, S::Error>>,
CT: ServiceFactory<h1::Control<F, S::Error>, Response = h1::ControlAck>,
CT::Error: Error,
CT::InitError: fmt::Debug,
{
HttpServiceBuilder {
config: self.config,
h2_control: self.h2_control,
h1_control: control.into_factory(),
_t: PhantomData,
}
}
pub fn h1<B, SF>(self, service: SF) -> H1Service<F, S, B, C1>
where
B: MessageBody,
SF: IntoServiceFactory<S, Request>,
S::Error: ResponseError,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>>,
{
H1Service::with_config(self.config, service.into_factory()).control(self.h1_control)
}
pub fn h2_control<CF, CT>(self, control: CF) -> HttpServiceBuilder<F, S, C1, CT>
where
CF: IntoServiceFactory<CT, h2::Control<H2Error>>,
CT: ServiceFactory<h2::Control<H2Error>, Response = h2::ControlAck>,
CT::Error: Error,
CT::InitError: fmt::Debug,
{
HttpServiceBuilder {
config: self.config,
h1_control: self.h1_control,
h2_control: control.into_factory(),
_t: PhantomData,
}
}
pub fn h2_configure<O, R>(self, f: O) -> Self
where
O: FnOnce(&h2::Config) -> R,
{
let _ = f(&self.config.h2config);
self
}
pub fn h2<B, SF>(self, service: SF) -> H2Service<F, S, B, C2>
where
B: MessageBody + 'static,
SF: IntoServiceFactory<S, Request>,
S::Error: ResponseError + 'static,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static,
{
H2Service::with_config(self.config, service.into_factory()).control(self.h2_control)
}
pub fn finish<B, SF>(self, service: SF) -> HttpService<F, S, B, C1, C2>
where
B: MessageBody + 'static,
SF: IntoServiceFactory<S, Request>,
S::Error: ResponseError + 'static,
S::InitError: fmt::Debug,
S::Response: Into<Response<B>> + 'static,
{
HttpService::with_config(self.config, service.into_factory())
.h1_control(self.h1_control)
.h2_control(self.h2_control)
}
}