2018-01-12 03:35:05 +01:00
|
|
|
//! Http server
|
|
|
|
use std::{time, io};
|
|
|
|
use std::net::Shutdown;
|
|
|
|
|
|
|
|
use futures::Poll;
|
|
|
|
use tokio_io::{AsyncRead, AsyncWrite};
|
2018-01-12 07:06:06 +01:00
|
|
|
use tokio_core::net::TcpStream;
|
2018-01-12 03:35:05 +01:00
|
|
|
|
|
|
|
mod srv;
|
|
|
|
mod worker;
|
|
|
|
mod channel;
|
2018-01-12 03:41:33 +01:00
|
|
|
mod encoding;
|
2018-01-12 03:35:05 +01:00
|
|
|
mod h1;
|
|
|
|
mod h2;
|
|
|
|
mod h1writer;
|
|
|
|
mod h2writer;
|
|
|
|
mod settings;
|
2018-01-12 06:48:36 +01:00
|
|
|
mod utils;
|
2018-01-12 03:35:05 +01:00
|
|
|
|
|
|
|
pub use self::srv::HttpServer;
|
|
|
|
pub use self::settings::ServerSettings;
|
|
|
|
|
|
|
|
use error::Error;
|
|
|
|
use httprequest::{HttpMessage, HttpRequest};
|
|
|
|
use httpresponse::HttpResponse;
|
|
|
|
|
|
|
|
/// max buffer size 64k
|
|
|
|
pub(crate) const MAX_WRITE_BUFFER_SIZE: usize = 65_536;
|
|
|
|
|
|
|
|
/// Pause accepting incoming connections
|
|
|
|
///
|
|
|
|
/// If socket contains some pending connection, they might be dropped.
|
|
|
|
/// All opened connection remains active.
|
|
|
|
#[derive(Message)]
|
|
|
|
pub struct PauseServer;
|
|
|
|
|
|
|
|
/// Resume accepting incoming connections
|
|
|
|
#[derive(Message)]
|
|
|
|
pub struct ResumeServer;
|
|
|
|
|
|
|
|
/// Stop incoming connection processing, stop all workers and exit.
|
|
|
|
///
|
|
|
|
/// If server starts with `spawn()` method, then spawned thread get terminated.
|
|
|
|
#[derive(Message)]
|
|
|
|
pub struct StopServer {
|
|
|
|
pub graceful: bool
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Low level http request handler
|
|
|
|
#[allow(unused_variables)]
|
|
|
|
pub trait HttpHandler: 'static {
|
|
|
|
|
|
|
|
/// Handle request
|
|
|
|
fn handle(&mut self, req: HttpRequest) -> Result<Box<HttpHandlerTask>, HttpRequest>;
|
|
|
|
}
|
|
|
|
|
2018-01-14 03:58:17 +01:00
|
|
|
impl HttpHandler for Box<HttpHandler> {
|
|
|
|
fn handle(&mut self, req: HttpRequest) -> Result<Box<HttpHandlerTask>, HttpRequest> {
|
|
|
|
self.as_mut().handle(req)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-12 03:35:05 +01:00
|
|
|
pub trait HttpHandlerTask {
|
|
|
|
|
|
|
|
fn poll(&mut self) -> Poll<(), Error>;
|
|
|
|
|
2018-01-12 07:06:06 +01:00
|
|
|
fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error>;
|
|
|
|
|
2018-01-12 03:35:05 +01:00
|
|
|
fn disconnected(&mut self);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Conversion helper trait
|
|
|
|
pub trait IntoHttpHandler {
|
|
|
|
/// The associated type which is result of conversion.
|
|
|
|
type Handler: HttpHandler;
|
|
|
|
|
|
|
|
/// Convert into `HttpHandler` object.
|
|
|
|
fn into_handler(self, settings: ServerSettings) -> Self::Handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: HttpHandler> IntoHttpHandler for T {
|
|
|
|
type Handler = T;
|
|
|
|
|
|
|
|
fn into_handler(self, _: ServerSettings) -> Self::Handler {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum WriterState {
|
|
|
|
Done,
|
|
|
|
Pause,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Stream writer
|
|
|
|
pub trait Writer {
|
|
|
|
fn written(&self) -> u64;
|
|
|
|
|
|
|
|
fn start(&mut self, req: &mut HttpMessage, resp: &mut HttpResponse)
|
|
|
|
-> Result<WriterState, io::Error>;
|
|
|
|
|
|
|
|
fn write(&mut self, payload: &[u8]) -> Result<WriterState, io::Error>;
|
|
|
|
|
|
|
|
fn write_eof(&mut self) -> Result<WriterState, io::Error>;
|
|
|
|
|
|
|
|
fn flush(&mut self) -> Poll<(), io::Error>;
|
|
|
|
|
|
|
|
fn poll_completed(&mut self, shutdown: bool) -> Poll<(), io::Error>;
|
|
|
|
}
|
2018-01-12 07:06:06 +01:00
|
|
|
|
|
|
|
/// Low-level io stream operations
|
|
|
|
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<()>;
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature="alpn")]
|
|
|
|
use tokio_openssl::SslStream;
|
|
|
|
|
|
|
|
#[cfg(feature="alpn")]
|
|
|
|
impl IoStream for SslStream<TcpStream> {
|
|
|
|
#[inline]
|
|
|
|
fn shutdown(&mut self, _how: Shutdown) -> io::Result<()> {
|
|
|
|
let _ = self.get_mut().shutdown();
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
|
|
|
|
self.get_mut().get_mut().set_nodelay(nodelay)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
|
|
|
|
self.get_mut().get_mut().set_linger(dur)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature="tls")]
|
|
|
|
use tokio_tls::TlsStream;
|
|
|
|
|
|
|
|
#[cfg(feature="tls")]
|
|
|
|
impl IoStream for TlsStream<TcpStream> {
|
|
|
|
#[inline]
|
|
|
|
fn shutdown(&mut self, _how: Shutdown) -> io::Result<()> {
|
|
|
|
let _ = self.get_mut().shutdown();
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
|
|
|
|
self.get_mut().get_mut().set_nodelay(nodelay)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn set_linger(&mut self, dur: Option<time::Duration>) -> io::Result<()> {
|
|
|
|
self.get_mut().get_mut().set_linger(dur)
|
|
|
|
}
|
|
|
|
}
|