use std::net::Shutdown;
use std::rc::Rc;
use std::{io, net, time};
use bytes::{BufMut, BytesMut};
use futures::{Async, Future, Poll};
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_reactor::Handle;
use tokio_tcp::TcpStream;
pub(crate) mod accept;
mod channel;
mod error;
pub(crate) mod h1;
pub(crate) mod h1decoder;
mod h1writer;
mod h2;
mod h2writer;
pub(crate) mod helpers;
mod http;
pub(crate) mod input;
pub(crate) mod message;
pub(crate) mod output;
mod server;
pub(crate) mod settings;
mod ssl;
mod worker;
use actix::Message;
pub use self::message::Request;
pub use self::http::HttpServer;
#[doc(hidden)]
pub use self::server::{
ConnectionRateTag, ConnectionTag, Connections, Server, Service, ServiceHandler,
};
pub use self::settings::ServerSettings;
#[doc(hidden)]
pub use self::ssl::*;
#[doc(hidden)]
pub use self::helpers::write_content_length;
use body::Binary;
use error::Error;
use extensions::Extensions;
use header::ContentEncoding;
use httpresponse::HttpResponse;
pub(crate) const MAX_WRITE_BUFFER_SIZE: usize = 65_536;
const LW_BUFFER_SIZE: usize = 4096;
const HW_BUFFER_SIZE: usize = 32_768;
pub fn new<F, U, H>(factory: F) -> HttpServer<H>
where
F: Fn() -> U + Sync + Send + 'static,
U: IntoIterator<Item = H> + 'static,
H: IntoHttpHandler + 'static,
{
HttpServer::new(factory)
}
#[doc(hidden)]
bitflags! {
pub struct ServerFlags: u8 {
const HTTP1 = 0b0000_0001;
const HTTP2 = 0b0000_0010;
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum KeepAlive {
Timeout(usize),
Tcp(usize),
Os,
Disabled,
}
impl From<usize> for KeepAlive {
fn from(keepalive: usize) -> Self {
KeepAlive::Timeout(keepalive)
}
}
impl From<Option<usize>> for KeepAlive {
fn from(keepalive: Option<usize>) -> Self {
if let Some(keepalive) = keepalive {
KeepAlive::Timeout(keepalive)
} else {
KeepAlive::Disabled
}
}
}
#[derive(Message)]
pub struct PauseServer;
#[derive(Message)]
pub struct ResumeServer;
pub struct StopServer {
pub graceful: bool,
}
impl Message for StopServer {
type Result = Result<(), ()>;
}
#[doc(hidden)]
#[derive(Clone, Copy)]
pub struct Token(usize);
impl Token {
pub(crate) fn new(val: usize) -> Token {
Token(val)
}
}
#[allow(unused_variables)]
pub trait HttpHandler: 'static {
type Task: HttpHandlerTask;
fn handle(&self, req: Request) -> Result<Self::Task, Request>;
}
impl HttpHandler for Box<HttpHandler<Task = Box<HttpHandlerTask>>> {
type Task = Box<HttpHandlerTask>;
fn handle(&self, req: Request) -> Result<Box<HttpHandlerTask>, Request> {
self.as_ref().handle(req)
}
}
pub trait HttpHandlerTask {
fn poll_completed(&mut self) -> Poll<(), Error> {
Ok(Async::Ready(()))
}
fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error>;
fn disconnected(&mut self) {}
}
impl HttpHandlerTask for Box<HttpHandlerTask> {
fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error> {
self.as_mut().poll_io(io)
}
}
pub trait IntoHttpHandler {
type Handler: HttpHandler;
fn into_handler(self) -> Self::Handler;
}
impl<T: HttpHandler> IntoHttpHandler for T {
type Handler = T;
fn into_handler(self) -> Self::Handler {
self
}
}
pub(crate) trait IntoAsyncIo {
type Io: AsyncRead + AsyncWrite;
fn into_async_io(self) -> Result<Self::Io, io::Error>;
}
impl IntoAsyncIo for net::TcpStream {
type Io = TcpStream;
fn into_async_io(self) -> Result<Self::Io, io::Error> {
TcpStream::from_std(self, &Handle::default())
}
}
#[doc(hidden)]
pub trait AcceptorService<Io: AsyncRead + AsyncWrite>: Clone {
type Accepted: IoStream;
type Future: Future<Item = Self::Accepted, Error = io::Error> + 'static;
fn accept(&self, io: Io) -> Self::Future;
fn scheme(&self) -> &'static str;
}
#[doc(hidden)]
#[derive(Debug)]
pub enum WriterState {
Done,
Pause,
}
#[doc(hidden)]
pub trait Writer {
fn written(&self) -> u64;
#[doc(hidden)]
fn set_date(&mut self);
#[doc(hidden)]
fn buffer(&mut self) -> &mut BytesMut;
fn start(
&mut self, req: &Request, resp: &mut HttpResponse, encoding: ContentEncoding,
) -> io::Result<WriterState>;
fn write(&mut self, payload: &Binary) -> io::Result<WriterState>;
fn write_eof(&mut self) -> io::Result<WriterState>;
fn poll_completed(&mut self, shutdown: bool) -> Poll<(), io::Error>;
}
#[doc(hidden)]
pub trait IoStream: AsyncRead + AsyncWrite + 'static {
fn shutdown(&mut self, how: Shutdown) -> io::Result<()>;
fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()>;
fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()>;
fn read_available(&mut self, buf: &mut BytesMut) -> Poll<(bool, bool), io::Error> {
let mut read_some = false;
loop {
if buf.remaining_mut() < LW_BUFFER_SIZE {
buf.reserve(HW_BUFFER_SIZE);
}
unsafe {
match self.read(buf.bytes_mut()) {
Ok(n) => {
if n == 0 {
return Ok(Async::Ready((read_some, true)));
} else {
read_some = true;
buf.advance_mut(n);
}
}
Err(e) => {
return if e.kind() == io::ErrorKind::WouldBlock {
if read_some {
Ok(Async::Ready((read_some, false)))
} else {
Ok(Async::NotReady)
}
} else {
Err(e)
};
}
}
}
}
}
fn extensions(&self) -> Option<Rc<Extensions>> {
None
}
}
#[cfg(all(unix, feature = "uds"))]
impl IoStream for ::tokio_uds::UnixStream {
#[inline]
fn shutdown(&mut self, how: Shutdown) -> io::Result<()> {
::tokio_uds::UnixStream::shutdown(self, how)
}
#[inline]
fn set_nodelay(&mut self, _nodelay: bool) -> io::Result<()> {
Ok(())
}
#[inline]
fn set_linger(&mut self, _dur: Option<time::Duration>) -> io::Result<()> {
Ok(())
}
}
impl IoStream for TcpStream {
#[inline]
fn shutdown(&mut self, how: Shutdown) -> io::Result<()> {
TcpStream::shutdown(self, how)
}
#[inline]
fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
TcpStream::set_nodelay(self, nodelay)
}
#[inline]
fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
TcpStream::set_linger(self, dur)
}
}