1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-24 16:02:59 +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"
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"

View File

@ -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<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]
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};
}

View File

@ -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<E: Debug + Display> {
// #[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<E: Debug + Display> {
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> {
fn from(err: ParseError) -> Self {
HttpDispatchError::Parse(err)
@ -82,9 +71,3 @@ impl<E: Debug + Display> From<io::Error> for HttpDispatchError<E> {
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 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<Extensions>,
pub(crate) addr: Option<SocketAddr>,
pub(crate) info: RefCell<ConnectionInfo>,
pub(crate) payload: RefCell<Option<Payload>>,
pub(crate) settings: ServerSettings,
pub(crate) stream_extensions: Option<Rc<Extensions>>,
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<SocketAddr> {
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<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
#[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<VecDeque<Rc<InnerRequest>>>, RefCell<ServerSettings>);
pub struct RequestPool(RefCell<VecDeque<Rc<InnerRequest>>>);
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)
}
}

View File

@ -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;

View File

@ -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<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()
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<Delay> {
@ -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)
}
}