diff --git a/Cargo.toml b/Cargo.toml index 870f772e8..455b61488 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,15 +30,12 @@ path = "src/lib.rs" [features] default = ["session", "cell"] -# tls +# native-tls tls = ["native-tls", "tokio-tls", "actix-net/tls"] # openssl ssl = ["openssl", "tokio-openssl", "actix-net/ssl"] -# deprecated, use "ssl" -alpn = ["openssl", "tokio-openssl", "actix-net/ssl"] - # rustls rust-tls = ["rustls", "tokio-rustls", "webpki", "webpki-roots", "actix-net/rust-tls"] @@ -61,7 +58,6 @@ http = "^0.1.8" httparse = "1.3" log = "0.4" mime = "0.3" -percent-encoding = "1.0" rand = "0.5" serde = "1.0" serde_json = "1.0" diff --git a/src/config.rs b/src/config.rs index 36b949c33..4e85044f1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,11 +10,36 @@ use time; use tokio_current_thread::spawn; use tokio_timer::{sleep, Delay}; -use server::KeepAlive; - // "Sun, 06 Nov 1994 08:49:37 GMT".len() const DATE_VALUE_LENGTH: usize = 29; +#[derive(Debug, PartialEq, Clone, Copy)] +/// Server keep-alive setting +pub enum KeepAlive { + /// Keep alive in seconds + Timeout(usize), + /// Relay on OS to shutdown tcp connection + Os, + /// Disabled + Disabled, +} + +impl From for KeepAlive { + fn from(keepalive: usize) -> Self { + KeepAlive::Timeout(keepalive) + } +} + +impl From> for KeepAlive { + fn from(keepalive: Option) -> Self { + if let Some(keepalive) = keepalive { + KeepAlive::Timeout(keepalive) + } else { + KeepAlive::Disabled + } + } +} + /// Http service configuration pub struct ServiceConfig(Rc); diff --git a/src/header.rs b/src/header.rs index 7b32d6c24..b1ba6524a 100644 --- a/src/header.rs +++ b/src/header.rs @@ -1,13 +1,8 @@ //! Various http headers -use std::fmt; -use std::str::FromStr; - -use bytes::{Bytes, BytesMut}; +use bytes::Bytes; use mime::Mime; -use modhttp::header::GetAll; use modhttp::Error as HttpError; -use percent_encoding; pub use modhttp::header::*; @@ -159,107 +154,3 @@ impl<'a> From<&'a str> for ContentEncoding { } } } - -#[doc(hidden)] -pub(crate) struct Writer { - buf: BytesMut, -} - -impl Writer { - fn new() -> Writer { - Writer { - buf: BytesMut::new(), - } - } - fn take(&mut self) -> Bytes { - self.buf.take().freeze() - } -} - -impl fmt::Write for Writer { - #[inline] - fn write_str(&mut self, s: &str) -> fmt::Result { - self.buf.extend_from_slice(s.as_bytes()); - Ok(()) - } - - #[inline] - fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result { - fmt::write(self, args) - } -} - -#[inline] -#[doc(hidden)] -/// Reads a comma-delimited raw header into a Vec. -pub fn from_comma_delimited( - all: GetAll, -) -> Result, ParseError> { - let mut result = Vec::new(); - for h in all { - let s = h.to_str().map_err(|_| ParseError::Header)?; - result.extend( - s.split(',') - .filter_map(|x| match x.trim() { - "" => None, - y => Some(y), - }).filter_map(|x| x.trim().parse().ok()), - ) - } - Ok(result) -} - -#[inline] -#[doc(hidden)] -/// Reads a single string when parsing a header. -pub fn from_one_raw_str(val: Option<&HeaderValue>) -> Result { - if let Some(line) = val { - let line = line.to_str().map_err(|_| ParseError::Header)?; - if !line.is_empty() { - return T::from_str(line).or(Err(ParseError::Header)); - } - } - Err(ParseError::Header) -} - -#[inline] -#[doc(hidden)] -/// Format an array into a comma-delimited string. -pub fn fmt_comma_delimited(f: &mut fmt::Formatter, parts: &[T]) -> fmt::Result -where - T: fmt::Display, -{ - let mut iter = parts.iter(); - if let Some(part) = iter.next() { - fmt::Display::fmt(part, f)?; - } - for part in iter { - f.write_str(", ")?; - fmt::Display::fmt(part, f)?; - } - Ok(()) -} - -/// Percent encode a sequence of bytes with a character set defined in -/// [https://tools.ietf.org/html/rfc5987#section-3.2][url] -/// -/// [url]: https://tools.ietf.org/html/rfc5987#section-3.2 -pub fn http_percent_encode(f: &mut fmt::Formatter, bytes: &[u8]) -> fmt::Result { - let encoded = - percent_encoding::percent_encode(bytes, self::percent_encoding_http::HTTP_VALUE); - fmt::Display::fmt(&encoded, f) -} -mod percent_encoding_http { - use percent_encoding; - - // internal module because macro is hard-coded to make a public item - // but we don't want to public export this item - define_encode_set! { - // This encode set is used for HTTP header values and is defined at - // https://tools.ietf.org/html/rfc5987#section-3.2 - pub HTTP_VALUE = [percent_encoding::SIMPLE_ENCODE_SET] | { - ' ', '"', '%', '\'', '(', ')', '*', ',', '/', ':', ';', '<', '-', '>', '?', - '[', '\\', ']', '{', '}' - } - } -} diff --git a/src/lib.rs b/src/lib.rs index 7efb4deab..accad2fbb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -106,6 +106,7 @@ extern crate mime; extern crate net2; extern crate rand; extern crate serde; +extern crate serde_json; extern crate serde_urlencoded; extern crate tokio; extern crate tokio_codec; @@ -117,9 +118,6 @@ extern crate tokio_timer; #[cfg(all(unix, feature = "uds"))] extern crate tokio_uds; extern crate url; -#[macro_use] -extern crate percent_encoding; -extern crate serde_json; #[cfg(test)] #[macro_use] @@ -140,7 +138,6 @@ mod uri; pub mod error; pub mod h1; pub(crate) mod helpers; -pub mod server; pub mod test; //pub mod ws; pub use body::{Binary, Body}; @@ -151,7 +148,7 @@ pub use httpresponse::HttpResponse; pub use json::Json; pub use request::Request; -pub use self::config::{ServiceConfig, ServiceConfigBuilder}; +pub use self::config::{KeepAlive, ServiceConfig, ServiceConfigBuilder}; pub mod dev { //! The `actix-web` prelude for library developers diff --git a/src/server/mod.rs b/src/server/mod.rs deleted file mode 100644 index 972fbf3fc..000000000 --- a/src/server/mod.rs +++ /dev/null @@ -1,204 +0,0 @@ -//! Http server module -//! -//! The module contains everything necessary to setup -//! HTTP server. -//! -//! In order to start HTTP server, first you need to create and configure it -//! using factory that can be supplied to [new](fn.new.html). -//! -//! ## Factory -//! -//! Factory is a function that returns Application, describing how -//! to serve incoming HTTP requests. -//! -//! As the server uses worker pool, the factory function is restricted to trait bounds -//! `Sync + Send + 'static` so that each worker would be able to accept Application -//! without a need for synchronization. -//! -//! If you wish to share part of state among all workers you should -//! wrap it in `Arc` and potentially synchronization primitive like -//! [RwLock](https://doc.rust-lang.org/std/sync/struct.RwLock.html) -//! If the wrapped type is not thread safe. -//! -//! Note though that locking is not advisable for asynchronous programming -//! and you should minimize all locks in your request handlers -//! -//! ## HTTPS Support -//! -//! Actix-web provides support for major crates that provides TLS. -//! Each TLS implementation is provided with [AcceptorService](trait.AcceptorService.html) -//! that describes how HTTP Server accepts connections. -//! -//! For `bind` and `listen` there are corresponding `bind_with` and `listen_with` that accepts -//! these services. -//! -//! By default, acceptor would work with both HTTP2 and HTTP1 protocols. -//! But it can be controlled using [ServerFlags](struct.ServerFlags.html) which -//! can be supplied when creating `AcceptorService`. -//! -//! **NOTE:** `native-tls` doesn't support `HTTP2` yet -//! -//! ## Signal handling and shutdown -//! -//! By default HTTP Server listens for system signals -//! and, gracefully shuts down at most after 30 seconds. -//! -//! Both signal handling and shutdown timeout can be controlled -//! using corresponding methods. -//! -//! If worker, for some reason, unable to shut down within timeout -//! it is forcibly dropped. -//! -//! ## Example -//! -//! ```rust,ignore -//!extern crate actix; -//!extern crate actix_web; -//!extern crate rustls; -//! -//!use actix_web::{http, middleware, server, App, Error, HttpRequest, HttpResponse, Responder}; -//!use std::io::BufReader; -//!use rustls::internal::pemfile::{certs, rsa_private_keys}; -//!use rustls::{NoClientAuth, ServerConfig}; -//! -//!fn index(req: &HttpRequest) -> Result { -//! Ok(HttpResponse::Ok().content_type("text/plain").body("Welcome!")) -//!} -//! -//!fn load_ssl() -> ServerConfig { -//! use std::io::BufReader; -//! -//! const CERT: &'static [u8] = include_bytes!("../cert.pem"); -//! const KEY: &'static [u8] = include_bytes!("../key.pem"); -//! -//! let mut cert = BufReader::new(CERT); -//! let mut key = BufReader::new(KEY); -//! -//! let mut config = ServerConfig::new(NoClientAuth::new()); -//! let cert_chain = certs(&mut cert).unwrap(); -//! let mut keys = rsa_private_keys(&mut key).unwrap(); -//! config.set_single_cert(cert_chain, keys.remove(0)).unwrap(); -//! -//! config -//!} -//! -//!fn main() { -//! let sys = actix::System::new("http-server"); -//! // load ssl keys -//! let config = load_ssl(); -//! -//! // Create acceptor service for only HTTP1 protocol -//! // You can use ::new(config) to leave defaults -//! let acceptor = server::RustlsAcceptor::with_flags(config, actix_web::server::ServerFlags::HTTP1); -//! -//! // create and start server at once -//! server::new(|| { -//! App::new() -//! // register simple handler, handle all methods -//! .resource("/index.html", |r| r.f(index)) -//! })) -//! }).bind_with("127.0.0.1:8080", acceptor) -//! .unwrap() -//! .start(); -//! -//! println!("Started http server: 127.0.0.1:8080"); -//! //Run system so that server would start accepting connections -//! let _ = sys.run(); -//!} -//! ``` -use std::net::SocketAddr; -use std::{io, time}; - -use tokio_io::{AsyncRead, AsyncWrite}; -use tokio_tcp::TcpStream; - -pub use actix_net::server::{PauseServer, ResumeServer, StopServer}; - -#[doc(hidden)] -pub use super::helpers::write_content_length; - -// /// max buffer size 64k -// pub(crate) const MAX_WRITE_BUFFER_SIZE: usize = 65_536; - -#[derive(Debug, PartialEq, Clone, Copy)] -/// Server keep-alive setting -pub enum KeepAlive { - /// Keep alive in seconds - Timeout(usize), - /// Relay on OS to shutdown tcp connection - Os, - /// Disabled - Disabled, -} - -impl From for KeepAlive { - fn from(keepalive: usize) -> Self { - KeepAlive::Timeout(keepalive) - } -} - -impl From> for KeepAlive { - fn from(keepalive: Option) -> Self { - if let Some(keepalive) = keepalive { - KeepAlive::Timeout(keepalive) - } else { - KeepAlive::Disabled - } - } -} - -#[doc(hidden)] -/// Low-level io stream operations -pub trait IoStream: AsyncRead + AsyncWrite + 'static { - /// Returns the socket address of the remote peer of this TCP connection. - fn peer_addr(&self) -> Option { - None - } - - /// Sets the value of the TCP_NODELAY option on this socket. - fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()>; - - fn set_linger(&mut self, dur: Option) -> io::Result<()>; - - fn set_keepalive(&mut self, dur: Option) -> io::Result<()>; -} - -#[cfg(all(unix, feature = "uds"))] -impl IoStream for ::tokio_uds::UnixStream { - #[inline] - fn set_nodelay(&mut self, _nodelay: bool) -> io::Result<()> { - Ok(()) - } - - #[inline] - fn set_linger(&mut self, _dur: Option) -> io::Result<()> { - Ok(()) - } - - #[inline] - fn set_keepalive(&mut self, _nodelay: bool) -> io::Result<()> { - Ok(()) - } -} - -impl IoStream for TcpStream { - #[inline] - fn peer_addr(&self) -> Option { - TcpStream::peer_addr(self).ok() - } - - #[inline] - fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> { - TcpStream::set_nodelay(self, nodelay) - } - - #[inline] - fn set_linger(&mut self, dur: Option) -> io::Result<()> { - TcpStream::set_linger(self, dur) - } - - #[inline] - fn set_keepalive(&mut self, dur: Option) -> io::Result<()> { - TcpStream::set_keepalive(self, dur) - } -} diff --git a/tests/test_h1v2.rs b/tests/test_h1v2.rs index 77a6ecae5..bb9430659 100644 --- a/tests/test_h1v2.rs +++ b/tests/test_h1v2.rs @@ -11,8 +11,7 @@ use actix_net::server::Server; use actix_web::{client, test}; use futures::future; -use actix_http::server::KeepAlive; -use actix_http::{h1, Error, HttpResponse, ServiceConfig}; +use actix_http::{h1, Error, HttpResponse, KeepAlive, ServiceConfig}; #[test] fn test_h1_v2() {