2022-01-31 17:30:34 +00:00
|
|
|
use std::{fmt, marker::PhantomData, net, rc::Rc, time::Duration};
|
2019-03-09 10:39:06 -08:00
|
|
|
|
2019-04-08 14:51:16 -07:00
|
|
|
use actix_codec::Framed;
|
2019-11-15 15:54:11 +06:00
|
|
|
use actix_service::{IntoServiceFactory, Service, ServiceFactory};
|
2019-03-09 10:39:06 -08:00
|
|
|
|
2021-06-17 17:57:58 +01:00
|
|
|
use crate::{
|
2021-12-04 19:40:47 +00:00
|
|
|
body::{BoxBody, MessageBody},
|
2021-06-17 17:57:58 +01:00
|
|
|
h1::{self, ExpectHandler, H1Service, UpgradeHandler},
|
|
|
|
h2::H2Service,
|
|
|
|
service::HttpService,
|
2022-01-31 17:30:34 +00:00
|
|
|
ConnectCallback, Extensions, KeepAlive, Request, Response, ServiceConfig,
|
2021-06-17 17:57:58 +01:00
|
|
|
};
|
2019-03-09 10:39:06 -08:00
|
|
|
|
2022-01-31 17:30:34 +00:00
|
|
|
/// An HTTP service builder.
|
2019-03-09 10:39:06 -08:00
|
|
|
///
|
2022-01-31 17:30:34 +00:00
|
|
|
/// This type can construct an instance of [`HttpService`] through a builder-like pattern.
|
2021-01-04 07:47:04 +08:00
|
|
|
pub struct HttpServiceBuilder<T, S, X = ExpectHandler, U = UpgradeHandler> {
|
2019-03-09 10:39:06 -08:00
|
|
|
keep_alive: KeepAlive,
|
2022-01-31 17:30:34 +00:00
|
|
|
client_request_timeout: Duration,
|
|
|
|
client_disconnect_timeout: Duration,
|
2019-12-02 17:33:11 +06:00
|
|
|
secure: bool,
|
|
|
|
local_addr: Option<net::SocketAddr>,
|
2019-04-05 16:46:44 -07:00
|
|
|
expect: X,
|
2019-04-08 14:51:16 -07:00
|
|
|
upgrade: Option<U>,
|
2020-10-30 02:03:26 +00:00
|
|
|
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
|
2021-01-04 00:49:02 +00:00
|
|
|
_phantom: PhantomData<S>,
|
2019-03-09 10:39:06 -08:00
|
|
|
}
|
|
|
|
|
2022-01-31 17:30:34 +00:00
|
|
|
impl<T, S> Default for HttpServiceBuilder<T, S, ExpectHandler, UpgradeHandler>
|
2019-03-09 10:39:06 -08:00
|
|
|
where
|
2021-01-04 07:47:04 +08:00
|
|
|
S: ServiceFactory<Request, Config = ()>,
|
2021-12-04 19:40:47 +00:00
|
|
|
S::Error: Into<Response<BoxBody>> + 'static,
|
2019-04-05 16:46:44 -07:00
|
|
|
S::InitError: fmt::Debug,
|
2021-01-04 07:47:04 +08:00
|
|
|
<S::Service as Service<Request>>::Future: 'static,
|
2019-03-09 10:39:06 -08:00
|
|
|
{
|
2022-01-31 17:30:34 +00:00
|
|
|
fn default() -> Self {
|
2019-03-09 10:39:06 -08:00
|
|
|
HttpServiceBuilder {
|
2022-01-31 17:30:34 +00:00
|
|
|
// ServiceConfig parts (make sure defaults match)
|
|
|
|
keep_alive: KeepAlive::default(),
|
|
|
|
client_request_timeout: Duration::from_secs(5),
|
|
|
|
client_disconnect_timeout: Duration::ZERO,
|
2019-12-02 17:33:11 +06:00
|
|
|
secure: false,
|
|
|
|
local_addr: None,
|
2022-01-31 17:30:34 +00:00
|
|
|
|
|
|
|
// dispatcher parts
|
2019-04-05 16:46:44 -07:00
|
|
|
expect: ExpectHandler,
|
2019-04-08 14:51:16 -07:00
|
|
|
upgrade: None,
|
2020-10-30 02:03:26 +00:00
|
|
|
on_connect_ext: None,
|
2021-01-04 00:49:02 +00:00
|
|
|
_phantom: PhantomData,
|
2019-03-09 10:39:06 -08:00
|
|
|
}
|
|
|
|
}
|
2019-04-05 16:46:44 -07:00
|
|
|
}
|
2019-03-09 10:39:06 -08:00
|
|
|
|
2019-04-08 14:51:16 -07:00
|
|
|
impl<T, S, X, U> HttpServiceBuilder<T, S, X, U>
|
2019-04-05 16:46:44 -07:00
|
|
|
where
|
2021-01-04 07:47:04 +08:00
|
|
|
S: ServiceFactory<Request, Config = ()>,
|
2021-12-04 19:40:47 +00:00
|
|
|
S::Error: Into<Response<BoxBody>> + 'static,
|
2019-04-05 16:46:44 -07:00
|
|
|
S::InitError: fmt::Debug,
|
2021-01-04 07:47:04 +08:00
|
|
|
<S::Service as Service<Request>>::Future: 'static,
|
|
|
|
X: ServiceFactory<Request, Config = (), Response = Request>,
|
2021-12-04 19:40:47 +00:00
|
|
|
X::Error: Into<Response<BoxBody>>,
|
2019-04-05 16:46:44 -07:00
|
|
|
X::InitError: fmt::Debug,
|
2021-06-17 17:57:58 +01:00
|
|
|
U: ServiceFactory<(Request, Framed<T, h1::Codec>), Config = (), Response = ()>,
|
2019-04-08 14:51:16 -07:00
|
|
|
U::Error: fmt::Display,
|
|
|
|
U::InitError: fmt::Debug,
|
2019-04-05 16:46:44 -07:00
|
|
|
{
|
2022-01-31 17:30:34 +00:00
|
|
|
/// Set connection keep-alive setting.
|
|
|
|
///
|
|
|
|
/// Applies to HTTP/1.1 keep-alive and HTTP/2 ping-pong.
|
2019-03-09 10:39:06 -08:00
|
|
|
///
|
2022-01-31 17:30:34 +00:00
|
|
|
/// By default keep-alive is 5 seconds.
|
2019-04-08 14:51:16 -07:00
|
|
|
pub fn keep_alive<W: Into<KeepAlive>>(mut self, val: W) -> Self {
|
2019-03-09 10:39:06 -08:00
|
|
|
self.keep_alive = val.into();
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-12-02 17:33:11 +06:00
|
|
|
/// Set connection secure state
|
|
|
|
pub fn secure(mut self) -> Self {
|
|
|
|
self.secure = true;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set the local address that this service is bound to.
|
|
|
|
pub fn local_addr(mut self, addr: net::SocketAddr) -> Self {
|
|
|
|
self.local_addr = Some(addr);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2022-01-31 17:30:34 +00:00
|
|
|
/// Set client request timeout (for first request).
|
2019-03-09 10:39:06 -08:00
|
|
|
///
|
2022-01-31 17:30:34 +00:00
|
|
|
/// Defines a timeout for reading client request header. If the client does not transmit the
|
|
|
|
/// request head within this duration, the connection is terminated with a `408 Request Timeout`
|
|
|
|
/// response error.
|
2019-03-09 10:39:06 -08:00
|
|
|
///
|
2022-01-31 17:30:34 +00:00
|
|
|
/// A duration of zero disables the timeout.
|
2019-03-09 10:39:06 -08:00
|
|
|
///
|
2022-01-31 17:30:34 +00:00
|
|
|
/// By default, the client timeout is 5 seconds.
|
|
|
|
pub fn client_request_timeout(mut self, dur: Duration) -> Self {
|
|
|
|
self.client_request_timeout = dur;
|
2019-03-09 10:39:06 -08:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2022-01-31 17:30:34 +00:00
|
|
|
#[doc(hidden)]
|
|
|
|
#[deprecated(since = "3.0.0", note = "Renamed to `client_request_timeout`.")]
|
|
|
|
pub fn client_timeout(self, dur: Duration) -> Self {
|
|
|
|
self.client_request_timeout(dur)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set client connection disconnect timeout.
|
2019-03-09 10:39:06 -08:00
|
|
|
///
|
|
|
|
/// Defines a timeout for disconnect connection. If a disconnect procedure does not complete
|
|
|
|
/// within this time, the request get dropped. This timeout affects secure connections.
|
|
|
|
///
|
2022-01-31 17:30:34 +00:00
|
|
|
/// A duration of zero disables the timeout.
|
2019-03-09 10:39:06 -08:00
|
|
|
///
|
2022-01-31 17:30:34 +00:00
|
|
|
/// By default, the disconnect timeout is disabled.
|
|
|
|
pub fn client_disconnect_timeout(mut self, dur: Duration) -> Self {
|
|
|
|
self.client_disconnect_timeout = dur;
|
2019-03-09 10:39:06 -08:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2022-01-31 17:30:34 +00:00
|
|
|
#[doc(hidden)]
|
|
|
|
#[deprecated(since = "3.0.0", note = "Renamed to `client_disconnect_timeout`.")]
|
|
|
|
pub fn client_disconnect(self, dur: Duration) -> Self {
|
|
|
|
self.client_disconnect_timeout(dur)
|
|
|
|
}
|
|
|
|
|
2019-04-08 10:31:29 -07:00
|
|
|
/// Provide service for `EXPECT: 100-Continue` support.
|
|
|
|
///
|
|
|
|
/// Service get called with request that contains `EXPECT` header.
|
|
|
|
/// Service must return request in case of success, in that case
|
|
|
|
/// request will be forwarded to main service.
|
2019-04-08 14:51:16 -07:00
|
|
|
pub fn expect<F, X1>(self, expect: F) -> HttpServiceBuilder<T, S, X1, U>
|
2019-04-08 10:31:29 -07:00
|
|
|
where
|
2021-01-04 07:47:04 +08:00
|
|
|
F: IntoServiceFactory<X1, Request>,
|
|
|
|
X1: ServiceFactory<Request, Config = (), Response = Request>,
|
2021-12-04 19:40:47 +00:00
|
|
|
X1::Error: Into<Response<BoxBody>>,
|
2019-04-08 14:51:16 -07:00
|
|
|
X1::InitError: fmt::Debug,
|
2019-04-08 10:31:29 -07:00
|
|
|
{
|
|
|
|
HttpServiceBuilder {
|
|
|
|
keep_alive: self.keep_alive,
|
2022-01-31 17:30:34 +00:00
|
|
|
client_request_timeout: self.client_request_timeout,
|
|
|
|
client_disconnect_timeout: self.client_disconnect_timeout,
|
2019-12-02 17:33:11 +06:00
|
|
|
secure: self.secure,
|
|
|
|
local_addr: self.local_addr,
|
2019-11-15 15:54:11 +06:00
|
|
|
expect: expect.into_factory(),
|
2019-04-08 14:51:16 -07:00
|
|
|
upgrade: self.upgrade,
|
2020-10-30 02:03:26 +00:00
|
|
|
on_connect_ext: self.on_connect_ext,
|
2021-01-04 00:49:02 +00:00
|
|
|
_phantom: PhantomData,
|
2019-04-08 10:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-08 17:49:27 -07:00
|
|
|
/// Provide service for custom `Connection: UPGRADE` support.
|
|
|
|
///
|
|
|
|
/// If service is provided then normal requests handling get halted
|
|
|
|
/// and this service get called with original request and framed object.
|
|
|
|
pub fn upgrade<F, U1>(self, upgrade: F) -> HttpServiceBuilder<T, S, X, U1>
|
|
|
|
where
|
2021-06-17 17:57:58 +01:00
|
|
|
F: IntoServiceFactory<U1, (Request, Framed<T, h1::Codec>)>,
|
|
|
|
U1: ServiceFactory<(Request, Framed<T, h1::Codec>), Config = (), Response = ()>,
|
2019-04-08 17:49:27 -07:00
|
|
|
U1::Error: fmt::Display,
|
|
|
|
U1::InitError: fmt::Debug,
|
|
|
|
{
|
|
|
|
HttpServiceBuilder {
|
|
|
|
keep_alive: self.keep_alive,
|
2022-01-31 17:30:34 +00:00
|
|
|
client_request_timeout: self.client_request_timeout,
|
|
|
|
client_disconnect_timeout: self.client_disconnect_timeout,
|
2019-12-02 17:33:11 +06:00
|
|
|
secure: self.secure,
|
|
|
|
local_addr: self.local_addr,
|
2019-04-08 17:49:27 -07:00
|
|
|
expect: self.expect,
|
2019-11-15 15:54:11 +06:00
|
|
|
upgrade: Some(upgrade.into_factory()),
|
2020-10-30 02:03:26 +00:00
|
|
|
on_connect_ext: self.on_connect_ext,
|
2021-01-04 00:49:02 +00:00
|
|
|
_phantom: PhantomData,
|
2019-04-08 17:49:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-30 02:03:26 +00:00
|
|
|
/// Sets the callback to be run on connection establishment.
|
|
|
|
///
|
|
|
|
/// Has mutable access to a data container that will be merged into request extensions.
|
|
|
|
/// This enables transport layer data (like client certificates) to be accessed in middleware
|
|
|
|
/// and handlers.
|
|
|
|
pub fn on_connect_ext<F>(mut self, f: F) -> Self
|
|
|
|
where
|
|
|
|
F: Fn(&T, &mut Extensions) + 'static,
|
|
|
|
{
|
|
|
|
self.on_connect_ext = Some(Rc::new(f));
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Finish service configuration and create a HTTP Service for HTTP/1 protocol.
|
2019-12-02 17:33:11 +06:00
|
|
|
pub fn h1<F, B>(self, service: F) -> H1Service<T, S, B, X, U>
|
2019-03-09 10:39:06 -08:00
|
|
|
where
|
2019-11-20 23:33:22 +06:00
|
|
|
B: MessageBody,
|
2021-01-04 07:47:04 +08:00
|
|
|
F: IntoServiceFactory<S, Request>,
|
2021-12-04 19:40:47 +00:00
|
|
|
S::Error: Into<Response<BoxBody>>,
|
2019-04-05 16:46:44 -07:00
|
|
|
S::InitError: fmt::Debug,
|
2019-11-20 23:33:22 +06:00
|
|
|
S::Response: Into<Response<B>>,
|
2019-03-09 10:39:06 -08:00
|
|
|
{
|
|
|
|
let cfg = ServiceConfig::new(
|
|
|
|
self.keep_alive,
|
2022-01-31 17:30:34 +00:00
|
|
|
self.client_request_timeout,
|
|
|
|
self.client_disconnect_timeout,
|
2019-12-02 17:33:11 +06:00
|
|
|
self.secure,
|
|
|
|
self.local_addr,
|
2019-03-09 10:39:06 -08:00
|
|
|
);
|
2020-10-30 02:03:26 +00:00
|
|
|
|
2019-11-15 15:54:11 +06:00
|
|
|
H1Service::with_config(cfg, service.into_factory())
|
2019-04-08 14:51:16 -07:00
|
|
|
.expect(self.expect)
|
|
|
|
.upgrade(self.upgrade)
|
2020-10-30 02:03:26 +00:00
|
|
|
.on_connect_ext(self.on_connect_ext)
|
2019-03-09 10:39:06 -08:00
|
|
|
}
|
|
|
|
|
2020-10-30 02:03:26 +00:00
|
|
|
/// Finish service configuration and create a HTTP service for HTTP/2 protocol.
|
2019-12-02 17:33:11 +06:00
|
|
|
pub fn h2<F, B>(self, service: F) -> H2Service<T, S, B>
|
2019-03-09 10:39:06 -08:00
|
|
|
where
|
2021-01-04 07:47:04 +08:00
|
|
|
F: IntoServiceFactory<S, Request>,
|
2021-12-04 19:40:47 +00:00
|
|
|
S::Error: Into<Response<BoxBody>> + 'static,
|
2019-04-05 16:46:44 -07:00
|
|
|
S::InitError: fmt::Debug,
|
2019-11-19 18:54:19 +06:00
|
|
|
S::Response: Into<Response<B>> + 'static,
|
2021-05-05 18:36:02 +01:00
|
|
|
|
|
|
|
B: MessageBody + 'static,
|
2019-03-09 10:39:06 -08:00
|
|
|
{
|
|
|
|
let cfg = ServiceConfig::new(
|
|
|
|
self.keep_alive,
|
2022-01-31 17:30:34 +00:00
|
|
|
self.client_request_timeout,
|
|
|
|
self.client_disconnect_timeout,
|
2019-12-02 17:33:11 +06:00
|
|
|
self.secure,
|
|
|
|
self.local_addr,
|
2019-03-09 10:39:06 -08:00
|
|
|
);
|
2020-10-30 02:03:26 +00:00
|
|
|
|
2021-12-08 06:01:11 +00:00
|
|
|
H2Service::with_config(cfg, service.into_factory()).on_connect_ext(self.on_connect_ext)
|
2019-03-09 10:39:06 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Finish service configuration and create `HttpService` instance.
|
2019-12-02 17:33:11 +06:00
|
|
|
pub fn finish<F, B>(self, service: F) -> HttpService<T, S, B, X, U>
|
2019-03-09 10:39:06 -08:00
|
|
|
where
|
2021-01-04 07:47:04 +08:00
|
|
|
F: IntoServiceFactory<S, Request>,
|
2021-12-04 19:40:47 +00:00
|
|
|
S::Error: Into<Response<BoxBody>> + 'static,
|
2019-04-05 16:46:44 -07:00
|
|
|
S::InitError: fmt::Debug,
|
2019-11-19 18:54:19 +06:00
|
|
|
S::Response: Into<Response<B>> + 'static,
|
2021-05-05 18:36:02 +01:00
|
|
|
|
|
|
|
B: MessageBody + 'static,
|
2019-03-09 10:39:06 -08:00
|
|
|
{
|
|
|
|
let cfg = ServiceConfig::new(
|
|
|
|
self.keep_alive,
|
2022-01-31 17:30:34 +00:00
|
|
|
self.client_request_timeout,
|
|
|
|
self.client_disconnect_timeout,
|
2019-12-02 17:33:11 +06:00
|
|
|
self.secure,
|
|
|
|
self.local_addr,
|
2019-03-09 10:39:06 -08:00
|
|
|
);
|
2020-10-30 02:03:26 +00:00
|
|
|
|
2019-11-15 15:54:11 +06:00
|
|
|
HttpService::with_config(cfg, service.into_factory())
|
2019-04-08 14:51:16 -07:00
|
|
|
.expect(self.expect)
|
|
|
|
.upgrade(self.upgrade)
|
2020-10-30 02:03:26 +00:00
|
|
|
.on_connect_ext(self.on_connect_ext)
|
2019-03-09 10:39:06 -08:00
|
|
|
}
|
|
|
|
}
|