diff --git a/Cargo.toml b/Cargo.toml index 258301daa..60f14485f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,14 +66,11 @@ actix-net = { git="https://github.com/actix/actix-net.git" } base64 = "0.9" bitflags = "1.0" -h2 = "0.1" -htmlescape = "0.3" http = "^0.1.8" httparse = "1.3" log = "0.4" mime = "0.3" mime_guess = "2.0.0-alpha" -num_cpus = "1.0" percent-encoding = "1.0" rand = "0.5" regex = "1.0" @@ -85,8 +82,6 @@ time = "0.1" encoding = "0.2" language-tags = "0.2" lazy_static = "1.0" -lazycell = "1.0.0" -parking_lot = "0.6" serde_urlencoded = "^0.5.3" url = { version="1.7", features=["query_encoding"] } 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" # io -mio = "^0.6.13" net2 = "0.2" bytes = "0.4" byteorder = "1.2" futures = "0.1" -futures-cpupool = "0.1" -slab = "0.4" -tokio = "0.1" tokio-codec = "0.1" tokio-io = "0.1" tokio-tcp = "0.1" @@ -132,6 +123,7 @@ tokio-uds = { version="0.2", optional = true } actix-web = "0.7" env_logger = "0.5" serde_derive = "1.0" +tokio = "0.1" [build-dependencies] version_check = "0.1" diff --git a/src/error.rs b/src/error.rs index 724803805..ff2388de8 100644 --- a/src/error.rs +++ b/src/error.rs @@ -11,7 +11,6 @@ use failure::{self, Backtrace, Fail}; use futures::Canceled; use http::uri::InvalidUri; use http::{header, Error as HttpError, StatusCode}; -use http2::Error as Http2Error; use httparse; use serde::de::value::Error as DeError; use serde_json::error::Error as JsonError; @@ -350,9 +349,6 @@ pub enum PayloadError { /// Io error #[fail(display = "{}", _0)] Io(#[cause] IoError), - /// Http2 error - #[fail(display = "{}", _0)] - Http2(#[cause] Http2Error), } impl From for PayloadError { diff --git a/src/info.rs b/src/info.rs deleted file mode 100644 index 5a2f21805..000000000 --- a/src/info.rs +++ /dev/null @@ -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, - peer: Option, -} - -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"); - } -} diff --git a/src/lib.rs b/src/lib.rs index 6df1a770e..efd566187 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -99,20 +99,13 @@ extern crate lazy_static; #[macro_use] extern crate futures; extern crate cookie; -extern crate futures_cpupool; -extern crate htmlescape; extern crate http as modhttp; extern crate httparse; extern crate language_tags; -extern crate lazycell; extern crate mime; extern crate mime_guess; -extern crate mio; extern crate net2; -extern crate parking_lot; extern crate rand; -extern crate slab; -extern crate tokio; extern crate tokio_codec; extern crate tokio_current_thread; extern crate tokio_io; @@ -129,8 +122,6 @@ extern crate brotli2; extern crate encoding; #[cfg(feature = "flate2")] extern crate flate2; -extern crate h2 as http2; -extern crate num_cpus; extern crate serde_urlencoded; #[macro_use] extern crate percent_encoding; @@ -148,9 +139,7 @@ mod extensions; mod header; mod httpcodes; mod httpmessage; -//mod httprequest; mod httpresponse; -mod info; mod json; mod payload; mod uri; @@ -182,7 +171,6 @@ pub mod dev { pub use body::BodyStream; pub use httpmessage::{MessageBody, Readlines, UrlEncoded}; pub use httpresponse::HttpResponseBuilder; - pub use info::ConnectionInfo; pub use json::JsonBody; pub use payload::{Payload, PayloadBuffer}; } diff --git a/src/server/error.rs b/src/server/error.rs index d9e1239e1..7d5c67d1e 100644 --- a/src/server/error.rs +++ b/src/server/error.rs @@ -2,7 +2,6 @@ use std::fmt::{Debug, Display}; use std::io; use futures::{Async, Poll}; -use http2; use error::{Error, ParseError}; use http::{StatusCode, Version}; @@ -44,10 +43,6 @@ pub enum HttpDispatchError { // #[fail(display = "Connection shutdown timeout")] ShutdownTimeout, - /// HTTP2 error - // #[fail(display = "HTTP2 error: {}", _0)] - Http2(http2::Error), - /// Payload is not consumed // #[fail(display = "Task is completed but request's payload is not consumed")] PayloadIsNotConsumed, @@ -65,12 +60,6 @@ pub enum HttpDispatchError { Unknown, } -// impl From for HttpDispatchError { -// fn from(err: E) -> Self { -// HttpDispatchError::App(err) -// } -// } - impl From for HttpDispatchError { fn from(err: ParseError) -> Self { HttpDispatchError::Parse(err) @@ -82,9 +71,3 @@ impl From for HttpDispatchError { HttpDispatchError::Io(err) } } - -impl From for HttpDispatchError { - fn from(err: http2::Error) -> Self { - HttpDispatchError::Http2(err) - } -} diff --git a/src/server/message.rs b/src/server/message.rs index 74ec5f17c..c39302bab 100644 --- a/src/server/message.rs +++ b/src/server/message.rs @@ -8,9 +8,7 @@ use http::{header, HeaderMap, Method, Uri, Version}; use extensions::Extensions; use httpmessage::HttpMessage; -use info::ConnectionInfo; use payload::Payload; -use server::ServerSettings; use uri::Url as InnerUrl; bitflags! { @@ -33,9 +31,7 @@ pub(crate) struct InnerRequest { pub(crate) headers: HeaderMap, pub(crate) extensions: RefCell, pub(crate) addr: Option, - pub(crate) info: RefCell, pub(crate) payload: RefCell>, - pub(crate) settings: ServerSettings, pub(crate) stream_extensions: Option>, pool: &'static RequestPool, } @@ -70,18 +66,16 @@ impl HttpMessage for Request { impl Request { /// Create new RequestContext instance - pub(crate) fn new(pool: &'static RequestPool, settings: ServerSettings) -> Request { + pub(crate) fn new(pool: &'static RequestPool) -> Request { Request { inner: Rc::new(InnerRequest { pool, - settings, method: Method::GET, url: InnerUrl::default(), version: Version::HTTP_11, headers: HeaderMap::with_capacity(16), flags: Cell::new(MessageFlags::empty()), addr: None, - info: RefCell::new(ConnectionInfo::default()), payload: RefCell::new(None), extensions: RefCell::new(Extensions::new()), stream_extensions: None, @@ -144,9 +138,6 @@ impl Request { /// /// 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. - /// - /// To get client connection information `connection_info()` method should - /// be used. pub fn peer_addr(&self) -> Option { self.inner().addr } @@ -179,31 +170,12 @@ impl Request { self.inner().method == Method::CONNECT } - /// Get *ConnectionInfo* for the correct request. - pub fn connection_info(&self) -> Ref { - 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 #[inline] pub fn stream_extensions(&self) -> Option<&Extensions> { 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 { Request { inner: self.inner.clone(), @@ -241,24 +213,18 @@ impl fmt::Debug for Request { } } -pub struct RequestPool(RefCell>>, RefCell); +pub struct RequestPool(RefCell>>); thread_local!(static POOL: &'static RequestPool = RequestPool::create()); impl RequestPool { fn create() -> &'static RequestPool { - let pool = RequestPool( - RefCell::new(VecDeque::with_capacity(128)), - RefCell::new(ServerSettings::default()), - ); + let pool = RequestPool(RefCell::new(VecDeque::with_capacity(128))); Box::leak(Box::new(pool)) } - pub(crate) fn pool(settings: ServerSettings) -> &'static RequestPool { - POOL.with(|p| { - *p.1.borrow_mut() = settings; - *p - }) + pub(crate) fn pool() -> &'static RequestPool { + POOL.with(|p| *p) } #[inline] @@ -266,7 +232,7 @@ impl RequestPool { if let Some(msg) = pool.0.borrow_mut().pop_front() { Request { inner: msg } } else { - Request::new(pool, pool.1.borrow().clone()) + Request::new(pool) } } diff --git a/src/server/mod.rs b/src/server/mod.rs index 7d64a6e20..be172e646 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -130,10 +130,8 @@ pub(crate) mod output; // pub(crate) mod service; pub(crate) mod settings; -pub use self::message::Request; - pub use self::error::{AcceptorError, HttpDispatchError}; -pub use self::settings::ServerSettings; +pub use self::message::Request; #[doc(hidden)] pub mod h1disp; @@ -141,9 +139,6 @@ pub mod h1disp; #[doc(hidden)] pub use self::settings::{ServiceConfig, ServiceConfigBuilder}; -//#[doc(hidden)] -//pub use self::service::{H1Service, HttpService, StreamConfiguration}; - #[doc(hidden)] pub use self::helpers::write_content_length; diff --git a/src/server/settings.rs b/src/server/settings.rs index f21283590..b8b7e51f0 100644 --- a/src/server/settings.rs +++ b/src/server/settings.rs @@ -7,10 +7,7 @@ use std::{env, fmt, net}; use bytes::BytesMut; use futures::{future, Future}; -use futures_cpupool::CpuPool; use http::StatusCode; -use lazycell::LazyCell; -use parking_lot::Mutex; use time; use tokio_current_thread::spawn; use tokio_timer::{sleep, Delay}; @@ -20,109 +17,6 @@ use super::KeepAlive; use body::Body; 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 = { - 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, - 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() const DATE_VALUE_LENGTH: usize = 29; @@ -149,7 +43,6 @@ impl ServiceConfig { /// Create instance of `ServiceConfig` pub(crate) fn new( keep_alive: KeepAlive, client_timeout: u64, client_shutdown: u64, - settings: ServerSettings, ) -> ServiceConfig { let (keep_alive, ka_enabled) = match keep_alive { KeepAlive::Timeout(val) => (val as u64, true), @@ -168,7 +61,7 @@ impl ServiceConfig { client_timeout, client_shutdown, bytes: Rc::new(SharedBytesPool::new()), - messages: RequestPool::pool(settings), + messages: RequestPool::pool(), date: UnsafeCell::new((false, Date::new())), })) } @@ -211,9 +104,7 @@ impl ServiceConfig { // Unsafe: WorkerSetting is !Sync and !Send unsafe { (*self.0.date.get()).0 = false }; } -} -impl ServiceConfig { #[inline] /// Client timeout for first request. pub fn client_timer(&self) -> Option { @@ -412,15 +303,9 @@ impl ServiceConfigBuilder { /// Finish service configuration and create `ServiceConfig` object. 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 }; - ServiceConfig::new( - self.keep_alive, - self.client_timeout, - client_shutdown, - settings, - ) + ServiceConfig::new(self.keep_alive, self.client_timeout, client_shutdown) } }