1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-12-01 02:44:37 +01:00

remove ServerSettings

This commit is contained in:
Nikolay Kim 2018-10-04 17:34:57 -07:00
parent 6aa2de7b8d
commit b15b2dda22
8 changed files with 10 additions and 425 deletions

View File

@ -66,14 +66,11 @@ actix-net = { git="https://github.com/actix/actix-net.git" }
base64 = "0.9" base64 = "0.9"
bitflags = "1.0" bitflags = "1.0"
h2 = "0.1"
htmlescape = "0.3"
http = "^0.1.8" http = "^0.1.8"
httparse = "1.3" httparse = "1.3"
log = "0.4" log = "0.4"
mime = "0.3" mime = "0.3"
mime_guess = "2.0.0-alpha" mime_guess = "2.0.0-alpha"
num_cpus = "1.0"
percent-encoding = "1.0" percent-encoding = "1.0"
rand = "0.5" rand = "0.5"
regex = "1.0" regex = "1.0"
@ -85,8 +82,6 @@ time = "0.1"
encoding = "0.2" encoding = "0.2"
language-tags = "0.2" language-tags = "0.2"
lazy_static = "1.0" lazy_static = "1.0"
lazycell = "1.0.0"
parking_lot = "0.6"
serde_urlencoded = "^0.5.3" serde_urlencoded = "^0.5.3"
url = { version="1.7", features=["query_encoding"] } url = { version="1.7", features=["query_encoding"] }
cookie = { version="0.11", features=["percent-encode"] } cookie = { version="0.11", features=["percent-encode"] }
@ -96,14 +91,10 @@ flate2 = { version="^1.0.2", optional = true, default-features = false }
failure = "^0.1.2" failure = "^0.1.2"
# io # io
mio = "^0.6.13"
net2 = "0.2" net2 = "0.2"
bytes = "0.4" bytes = "0.4"
byteorder = "1.2" byteorder = "1.2"
futures = "0.1" futures = "0.1"
futures-cpupool = "0.1"
slab = "0.4"
tokio = "0.1"
tokio-codec = "0.1" tokio-codec = "0.1"
tokio-io = "0.1" tokio-io = "0.1"
tokio-tcp = "0.1" tokio-tcp = "0.1"
@ -132,6 +123,7 @@ tokio-uds = { version="0.2", optional = true }
actix-web = "0.7" actix-web = "0.7"
env_logger = "0.5" env_logger = "0.5"
serde_derive = "1.0" serde_derive = "1.0"
tokio = "0.1"
[build-dependencies] [build-dependencies]
version_check = "0.1" version_check = "0.1"

View File

@ -11,7 +11,6 @@ use failure::{self, Backtrace, Fail};
use futures::Canceled; use futures::Canceled;
use http::uri::InvalidUri; use http::uri::InvalidUri;
use http::{header, Error as HttpError, StatusCode}; use http::{header, Error as HttpError, StatusCode};
use http2::Error as Http2Error;
use httparse; use httparse;
use serde::de::value::Error as DeError; use serde::de::value::Error as DeError;
use serde_json::error::Error as JsonError; use serde_json::error::Error as JsonError;
@ -350,9 +349,6 @@ pub enum PayloadError {
/// Io error /// Io error
#[fail(display = "{}", _0)] #[fail(display = "{}", _0)]
Io(#[cause] IoError), Io(#[cause] IoError),
/// Http2 error
#[fail(display = "{}", _0)]
Http2(#[cause] Http2Error),
} }
impl From<IoError> for PayloadError { impl From<IoError> for PayloadError {

View File

@ -1,220 +0,0 @@
use http::header::{self, HeaderName};
use server::Request;
const X_FORWARDED_FOR: &[u8] = b"x-forwarded-for";
const X_FORWARDED_HOST: &[u8] = b"x-forwarded-host";
const X_FORWARDED_PROTO: &[u8] = b"x-forwarded-proto";
/// `HttpRequest` connection information
#[derive(Clone, Default)]
pub struct ConnectionInfo {
scheme: String,
host: String,
remote: Option<String>,
peer: Option<String>,
}
impl ConnectionInfo {
/// Create *ConnectionInfo* instance for a request.
#[cfg_attr(
feature = "cargo-clippy",
allow(clippy::cyclomatic_complexity)
)]
pub fn update(&mut self, req: &Request) {
let mut host = None;
let mut scheme = None;
let mut remote = None;
let mut peer = None;
// load forwarded header
for hdr in req.headers().get_all(header::FORWARDED) {
if let Ok(val) = hdr.to_str() {
for pair in val.split(';') {
for el in pair.split(',') {
let mut items = el.trim().splitn(2, '=');
if let Some(name) = items.next() {
if let Some(val) = items.next() {
match &name.to_lowercase() as &str {
"for" => if remote.is_none() {
remote = Some(val.trim());
},
"proto" => if scheme.is_none() {
scheme = Some(val.trim());
},
"host" => if host.is_none() {
host = Some(val.trim());
},
_ => (),
}
}
}
}
}
}
}
// scheme
if scheme.is_none() {
if let Some(h) = req
.headers()
.get(HeaderName::from_lowercase(X_FORWARDED_PROTO).unwrap())
{
if let Ok(h) = h.to_str() {
scheme = h.split(',').next().map(|v| v.trim());
}
}
if scheme.is_none() {
scheme = req.uri().scheme_part().map(|a| a.as_str());
if scheme.is_none() && req.server_settings().secure() {
scheme = Some("https")
}
}
}
// host
if host.is_none() {
if let Some(h) = req
.headers()
.get(HeaderName::from_lowercase(X_FORWARDED_HOST).unwrap())
{
if let Ok(h) = h.to_str() {
host = h.split(',').next().map(|v| v.trim());
}
}
if host.is_none() {
if let Some(h) = req.headers().get(header::HOST) {
host = h.to_str().ok();
}
if host.is_none() {
host = req.uri().authority_part().map(|a| a.as_str());
if host.is_none() {
host = Some(req.server_settings().host());
}
}
}
}
// remote addr
if remote.is_none() {
if let Some(h) = req
.headers()
.get(HeaderName::from_lowercase(X_FORWARDED_FOR).unwrap())
{
if let Ok(h) = h.to_str() {
remote = h.split(',').next().map(|v| v.trim());
}
}
if remote.is_none() {
// get peeraddr from socketaddr
peer = req.peer_addr().map(|addr| format!("{}", addr));
}
}
self.scheme = scheme.unwrap_or("http").to_owned();
self.host = host.unwrap_or("localhost").to_owned();
self.remote = remote.map(|s| s.to_owned());
self.peer = peer;
}
/// Scheme of the request.
///
/// Scheme is resolved through the following headers, in this order:
///
/// - Forwarded
/// - X-Forwarded-Proto
/// - Uri
#[inline]
pub fn scheme(&self) -> &str {
&self.scheme
}
/// Hostname of the request.
///
/// Hostname is resolved through the following headers, in this order:
///
/// - Forwarded
/// - X-Forwarded-Host
/// - Host
/// - Uri
/// - Server hostname
pub fn host(&self) -> &str {
&self.host
}
/// Remote IP of client initiated HTTP request.
///
/// The IP is resolved through the following headers, in this order:
///
/// - Forwarded
/// - X-Forwarded-For
/// - peer name of opened socket
#[inline]
pub fn remote(&self) -> Option<&str> {
if let Some(ref r) = self.remote {
Some(r)
} else if let Some(ref peer) = self.peer {
Some(peer)
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use test::TestRequest;
#[test]
fn test_forwarded() {
let req = TestRequest::default().request();
let mut info = ConnectionInfo::default();
info.update(&req);
assert_eq!(info.scheme(), "http");
assert_eq!(info.host(), "localhost:8080");
let req = TestRequest::default()
.header(
header::FORWARDED,
"for=192.0.2.60; proto=https; by=203.0.113.43; host=rust-lang.org",
).request();
let mut info = ConnectionInfo::default();
info.update(&req);
assert_eq!(info.scheme(), "https");
assert_eq!(info.host(), "rust-lang.org");
assert_eq!(info.remote(), Some("192.0.2.60"));
let req = TestRequest::default()
.header(header::HOST, "rust-lang.org")
.request();
let mut info = ConnectionInfo::default();
info.update(&req);
assert_eq!(info.scheme(), "http");
assert_eq!(info.host(), "rust-lang.org");
assert_eq!(info.remote(), None);
let req = TestRequest::default()
.header(X_FORWARDED_FOR, "192.0.2.60")
.request();
let mut info = ConnectionInfo::default();
info.update(&req);
assert_eq!(info.remote(), Some("192.0.2.60"));
let req = TestRequest::default()
.header(X_FORWARDED_HOST, "192.0.2.60")
.request();
let mut info = ConnectionInfo::default();
info.update(&req);
assert_eq!(info.host(), "192.0.2.60");
assert_eq!(info.remote(), None);
let req = TestRequest::default()
.header(X_FORWARDED_PROTO, "https")
.request();
let mut info = ConnectionInfo::default();
info.update(&req);
assert_eq!(info.scheme(), "https");
}
}

View File

@ -99,20 +99,13 @@ extern crate lazy_static;
#[macro_use] #[macro_use]
extern crate futures; extern crate futures;
extern crate cookie; extern crate cookie;
extern crate futures_cpupool;
extern crate htmlescape;
extern crate http as modhttp; extern crate http as modhttp;
extern crate httparse; extern crate httparse;
extern crate language_tags; extern crate language_tags;
extern crate lazycell;
extern crate mime; extern crate mime;
extern crate mime_guess; extern crate mime_guess;
extern crate mio;
extern crate net2; extern crate net2;
extern crate parking_lot;
extern crate rand; extern crate rand;
extern crate slab;
extern crate tokio;
extern crate tokio_codec; extern crate tokio_codec;
extern crate tokio_current_thread; extern crate tokio_current_thread;
extern crate tokio_io; extern crate tokio_io;
@ -129,8 +122,6 @@ extern crate brotli2;
extern crate encoding; extern crate encoding;
#[cfg(feature = "flate2")] #[cfg(feature = "flate2")]
extern crate flate2; extern crate flate2;
extern crate h2 as http2;
extern crate num_cpus;
extern crate serde_urlencoded; extern crate serde_urlencoded;
#[macro_use] #[macro_use]
extern crate percent_encoding; extern crate percent_encoding;
@ -148,9 +139,7 @@ mod extensions;
mod header; mod header;
mod httpcodes; mod httpcodes;
mod httpmessage; mod httpmessage;
//mod httprequest;
mod httpresponse; mod httpresponse;
mod info;
mod json; mod json;
mod payload; mod payload;
mod uri; mod uri;
@ -182,7 +171,6 @@ pub mod dev {
pub use body::BodyStream; pub use body::BodyStream;
pub use httpmessage::{MessageBody, Readlines, UrlEncoded}; pub use httpmessage::{MessageBody, Readlines, UrlEncoded};
pub use httpresponse::HttpResponseBuilder; pub use httpresponse::HttpResponseBuilder;
pub use info::ConnectionInfo;
pub use json::JsonBody; pub use json::JsonBody;
pub use payload::{Payload, PayloadBuffer}; pub use payload::{Payload, PayloadBuffer};
} }

View File

@ -2,7 +2,6 @@ use std::fmt::{Debug, Display};
use std::io; use std::io;
use futures::{Async, Poll}; use futures::{Async, Poll};
use http2;
use error::{Error, ParseError}; use error::{Error, ParseError};
use http::{StatusCode, Version}; use http::{StatusCode, Version};
@ -44,10 +43,6 @@ pub enum HttpDispatchError<E: Debug + Display> {
// #[fail(display = "Connection shutdown timeout")] // #[fail(display = "Connection shutdown timeout")]
ShutdownTimeout, ShutdownTimeout,
/// HTTP2 error
// #[fail(display = "HTTP2 error: {}", _0)]
Http2(http2::Error),
/// Payload is not consumed /// Payload is not consumed
// #[fail(display = "Task is completed but request's payload is not consumed")] // #[fail(display = "Task is completed but request's payload is not consumed")]
PayloadIsNotConsumed, PayloadIsNotConsumed,
@ -65,12 +60,6 @@ pub enum HttpDispatchError<E: Debug + Display> {
Unknown, Unknown,
} }
// impl<E: Debug + Display> From<E> for HttpDispatchError<E> {
// fn from(err: E) -> Self {
// HttpDispatchError::App(err)
// }
// }
impl<E: Debug + Display> From<ParseError> for HttpDispatchError<E> { impl<E: Debug + Display> From<ParseError> for HttpDispatchError<E> {
fn from(err: ParseError) -> Self { fn from(err: ParseError) -> Self {
HttpDispatchError::Parse(err) HttpDispatchError::Parse(err)
@ -82,9 +71,3 @@ impl<E: Debug + Display> From<io::Error> for HttpDispatchError<E> {
HttpDispatchError::Io(err) HttpDispatchError::Io(err)
} }
} }
impl<E: Debug + Display> From<http2::Error> for HttpDispatchError<E> {
fn from(err: http2::Error) -> Self {
HttpDispatchError::Http2(err)
}
}

View File

@ -8,9 +8,7 @@ use http::{header, HeaderMap, Method, Uri, Version};
use extensions::Extensions; use extensions::Extensions;
use httpmessage::HttpMessage; use httpmessage::HttpMessage;
use info::ConnectionInfo;
use payload::Payload; use payload::Payload;
use server::ServerSettings;
use uri::Url as InnerUrl; use uri::Url as InnerUrl;
bitflags! { bitflags! {
@ -33,9 +31,7 @@ pub(crate) struct InnerRequest {
pub(crate) headers: HeaderMap, pub(crate) headers: HeaderMap,
pub(crate) extensions: RefCell<Extensions>, pub(crate) extensions: RefCell<Extensions>,
pub(crate) addr: Option<SocketAddr>, pub(crate) addr: Option<SocketAddr>,
pub(crate) info: RefCell<ConnectionInfo>,
pub(crate) payload: RefCell<Option<Payload>>, pub(crate) payload: RefCell<Option<Payload>>,
pub(crate) settings: ServerSettings,
pub(crate) stream_extensions: Option<Rc<Extensions>>, pub(crate) stream_extensions: Option<Rc<Extensions>>,
pool: &'static RequestPool, pool: &'static RequestPool,
} }
@ -70,18 +66,16 @@ impl HttpMessage for Request {
impl Request { impl Request {
/// Create new RequestContext instance /// Create new RequestContext instance
pub(crate) fn new(pool: &'static RequestPool, settings: ServerSettings) -> Request { pub(crate) fn new(pool: &'static RequestPool) -> Request {
Request { Request {
inner: Rc::new(InnerRequest { inner: Rc::new(InnerRequest {
pool, pool,
settings,
method: Method::GET, method: Method::GET,
url: InnerUrl::default(), url: InnerUrl::default(),
version: Version::HTTP_11, version: Version::HTTP_11,
headers: HeaderMap::with_capacity(16), headers: HeaderMap::with_capacity(16),
flags: Cell::new(MessageFlags::empty()), flags: Cell::new(MessageFlags::empty()),
addr: None, addr: None,
info: RefCell::new(ConnectionInfo::default()),
payload: RefCell::new(None), payload: RefCell::new(None),
extensions: RefCell::new(Extensions::new()), extensions: RefCell::new(Extensions::new()),
stream_extensions: None, stream_extensions: None,
@ -144,9 +138,6 @@ impl Request {
/// ///
/// Peer address is actual socket address, if proxy is used in front of /// Peer address is actual socket address, if proxy is used in front of
/// actix http server, then peer address would be address of this proxy. /// actix http server, then peer address would be address of this proxy.
///
/// To get client connection information `connection_info()` method should
/// be used.
pub fn peer_addr(&self) -> Option<SocketAddr> { pub fn peer_addr(&self) -> Option<SocketAddr> {
self.inner().addr self.inner().addr
} }
@ -179,31 +170,12 @@ impl Request {
self.inner().method == Method::CONNECT self.inner().method == Method::CONNECT
} }
/// Get *ConnectionInfo* for the correct request.
pub fn connection_info(&self) -> Ref<ConnectionInfo> {
if self.inner().flags.get().contains(MessageFlags::CONN_INFO) {
self.inner().info.borrow()
} else {
let mut flags = self.inner().flags.get();
flags.insert(MessageFlags::CONN_INFO);
self.inner().flags.set(flags);
self.inner().info.borrow_mut().update(self);
self.inner().info.borrow()
}
}
/// Io stream extensions /// Io stream extensions
#[inline] #[inline]
pub fn stream_extensions(&self) -> Option<&Extensions> { pub fn stream_extensions(&self) -> Option<&Extensions> {
self.inner().stream_extensions.as_ref().map(|e| e.as_ref()) self.inner().stream_extensions.as_ref().map(|e| e.as_ref())
} }
/// Server settings
#[inline]
pub fn server_settings(&self) -> &ServerSettings {
&self.inner().settings
}
pub(crate) fn clone(&self) -> Self { pub(crate) fn clone(&self) -> Self {
Request { Request {
inner: self.inner.clone(), inner: self.inner.clone(),
@ -241,24 +213,18 @@ impl fmt::Debug for Request {
} }
} }
pub struct RequestPool(RefCell<VecDeque<Rc<InnerRequest>>>, RefCell<ServerSettings>); pub struct RequestPool(RefCell<VecDeque<Rc<InnerRequest>>>);
thread_local!(static POOL: &'static RequestPool = RequestPool::create()); thread_local!(static POOL: &'static RequestPool = RequestPool::create());
impl RequestPool { impl RequestPool {
fn create() -> &'static RequestPool { fn create() -> &'static RequestPool {
let pool = RequestPool( let pool = RequestPool(RefCell::new(VecDeque::with_capacity(128)));
RefCell::new(VecDeque::with_capacity(128)),
RefCell::new(ServerSettings::default()),
);
Box::leak(Box::new(pool)) Box::leak(Box::new(pool))
} }
pub(crate) fn pool(settings: ServerSettings) -> &'static RequestPool { pub(crate) fn pool() -> &'static RequestPool {
POOL.with(|p| { POOL.with(|p| *p)
*p.1.borrow_mut() = settings;
*p
})
} }
#[inline] #[inline]
@ -266,7 +232,7 @@ impl RequestPool {
if let Some(msg) = pool.0.borrow_mut().pop_front() { if let Some(msg) = pool.0.borrow_mut().pop_front() {
Request { inner: msg } Request { inner: msg }
} else { } else {
Request::new(pool, pool.1.borrow().clone()) Request::new(pool)
} }
} }

View File

@ -130,10 +130,8 @@ pub(crate) mod output;
// pub(crate) mod service; // pub(crate) mod service;
pub(crate) mod settings; pub(crate) mod settings;
pub use self::message::Request;
pub use self::error::{AcceptorError, HttpDispatchError}; pub use self::error::{AcceptorError, HttpDispatchError};
pub use self::settings::ServerSettings; pub use self::message::Request;
#[doc(hidden)] #[doc(hidden)]
pub mod h1disp; pub mod h1disp;
@ -141,9 +139,6 @@ pub mod h1disp;
#[doc(hidden)] #[doc(hidden)]
pub use self::settings::{ServiceConfig, ServiceConfigBuilder}; pub use self::settings::{ServiceConfig, ServiceConfigBuilder};
//#[doc(hidden)]
//pub use self::service::{H1Service, HttpService, StreamConfiguration};
#[doc(hidden)] #[doc(hidden)]
pub use self::helpers::write_content_length; pub use self::helpers::write_content_length;

View File

@ -7,10 +7,7 @@ use std::{env, fmt, net};
use bytes::BytesMut; use bytes::BytesMut;
use futures::{future, Future}; use futures::{future, Future};
use futures_cpupool::CpuPool;
use http::StatusCode; use http::StatusCode;
use lazycell::LazyCell;
use parking_lot::Mutex;
use time; use time;
use tokio_current_thread::spawn; use tokio_current_thread::spawn;
use tokio_timer::{sleep, Delay}; use tokio_timer::{sleep, Delay};
@ -20,109 +17,6 @@ use super::KeepAlive;
use body::Body; use body::Body;
use httpresponse::{HttpResponse, HttpResponseBuilder, HttpResponsePool}; use httpresponse::{HttpResponse, HttpResponseBuilder, HttpResponsePool};
/// Env variable for default cpu pool size
const ENV_CPU_POOL_VAR: &str = "ACTIX_CPU_POOL";
lazy_static! {
pub(crate) static ref DEFAULT_CPUPOOL: Mutex<CpuPool> = {
let default = match env::var(ENV_CPU_POOL_VAR) {
Ok(val) => {
if let Ok(val) = val.parse() {
val
} else {
error!("Can not parse ACTIX_CPU_POOL value");
20
}
}
Err(_) => 20,
};
Mutex::new(CpuPool::new(default))
};
}
/// Various server settings
pub struct ServerSettings {
addr: net::SocketAddr,
secure: bool,
host: String,
cpu_pool: LazyCell<CpuPool>,
responses: &'static HttpResponsePool,
}
impl Clone for ServerSettings {
fn clone(&self) -> Self {
ServerSettings {
addr: self.addr,
secure: self.secure,
host: self.host.clone(),
cpu_pool: LazyCell::new(),
responses: HttpResponsePool::get_pool(),
}
}
}
impl Default for ServerSettings {
fn default() -> Self {
ServerSettings {
addr: "127.0.0.1:8080".parse().unwrap(),
secure: false,
host: "localhost:8080".to_owned(),
responses: HttpResponsePool::get_pool(),
cpu_pool: LazyCell::new(),
}
}
}
impl ServerSettings {
/// Crate server settings instance
pub(crate) fn new(
addr: net::SocketAddr, host: &str, secure: bool,
) -> ServerSettings {
let host = host.to_owned();
let cpu_pool = LazyCell::new();
let responses = HttpResponsePool::get_pool();
ServerSettings {
addr,
secure,
host,
cpu_pool,
responses,
}
}
/// Returns the socket address of the local half of this TCP connection
pub fn local_addr(&self) -> net::SocketAddr {
self.addr
}
/// Returns true if connection is secure(https)
pub fn secure(&self) -> bool {
self.secure
}
/// Returns host header value
pub fn host(&self) -> &str {
&self.host
}
/// Returns default `CpuPool` for server
pub fn cpu_pool(&self) -> &CpuPool {
self.cpu_pool.borrow_with(|| DEFAULT_CPUPOOL.lock().clone())
}
#[inline]
pub(crate) fn get_response(&self, status: StatusCode, body: Body) -> HttpResponse {
HttpResponsePool::get_response(&self.responses, status, body)
}
#[inline]
pub(crate) fn get_response_builder(
&self, status: StatusCode,
) -> HttpResponseBuilder {
HttpResponsePool::get_builder(&self.responses, status)
}
}
// "Sun, 06 Nov 1994 08:49:37 GMT".len() // "Sun, 06 Nov 1994 08:49:37 GMT".len()
const DATE_VALUE_LENGTH: usize = 29; const DATE_VALUE_LENGTH: usize = 29;
@ -149,7 +43,6 @@ impl ServiceConfig {
/// Create instance of `ServiceConfig` /// Create instance of `ServiceConfig`
pub(crate) fn new( pub(crate) fn new(
keep_alive: KeepAlive, client_timeout: u64, client_shutdown: u64, keep_alive: KeepAlive, client_timeout: u64, client_shutdown: u64,
settings: ServerSettings,
) -> ServiceConfig { ) -> ServiceConfig {
let (keep_alive, ka_enabled) = match keep_alive { let (keep_alive, ka_enabled) = match keep_alive {
KeepAlive::Timeout(val) => (val as u64, true), KeepAlive::Timeout(val) => (val as u64, true),
@ -168,7 +61,7 @@ impl ServiceConfig {
client_timeout, client_timeout,
client_shutdown, client_shutdown,
bytes: Rc::new(SharedBytesPool::new()), bytes: Rc::new(SharedBytesPool::new()),
messages: RequestPool::pool(settings), messages: RequestPool::pool(),
date: UnsafeCell::new((false, Date::new())), date: UnsafeCell::new((false, Date::new())),
})) }))
} }
@ -211,9 +104,7 @@ impl ServiceConfig {
// Unsafe: WorkerSetting is !Sync and !Send // Unsafe: WorkerSetting is !Sync and !Send
unsafe { (*self.0.date.get()).0 = false }; unsafe { (*self.0.date.get()).0 = false };
} }
}
impl ServiceConfig {
#[inline] #[inline]
/// Client timeout for first request. /// Client timeout for first request.
pub fn client_timer(&self) -> Option<Delay> { pub fn client_timer(&self) -> Option<Delay> {
@ -412,15 +303,9 @@ impl ServiceConfigBuilder {
/// Finish service configuration and create `ServiceConfig` object. /// Finish service configuration and create `ServiceConfig` object.
pub fn finish(self) -> ServiceConfig { pub fn finish(self) -> ServiceConfig {
let settings = ServerSettings::new(self.addr, &self.host, self.secure);
let client_shutdown = if self.secure { self.client_shutdown } else { 0 }; let client_shutdown = if self.secure { self.client_shutdown } else { 0 };
ServiceConfig::new( ServiceConfig::new(self.keep_alive, self.client_timeout, client_shutdown)
self.keep_alive,
self.client_timeout,
client_shutdown,
settings,
)
} }
} }