mirror of
https://github.com/fafhrd91/actix-web
synced 2025-01-18 05:41:50 +01:00
move server protocol impl to submodule
This commit is contained in:
parent
fa93701bee
commit
8a058efb4e
@ -67,7 +67,7 @@ fn main() {
|
|||||||
|
|
||||||
let addr = rx.recv().unwrap();
|
let addr = rx.recv().unwrap();
|
||||||
let _ = addr.call_fut(
|
let _ = addr.call_fut(
|
||||||
dev::StopServer{graceful:true}).wait(); // <- Send `StopServer` message to server.
|
server::StopServer{graceful:true}).wait(); // <- Send `StopServer` message to server.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -8,10 +8,9 @@ use router::{Router, Pattern};
|
|||||||
use resource::Resource;
|
use resource::Resource;
|
||||||
use handler::{Handler, RouteHandler, WrapHandler};
|
use handler::{Handler, RouteHandler, WrapHandler};
|
||||||
use httprequest::HttpRequest;
|
use httprequest::HttpRequest;
|
||||||
use channel::{HttpHandler, IntoHttpHandler, HttpHandlerTask};
|
|
||||||
use pipeline::{Pipeline, PipelineHandler};
|
use pipeline::{Pipeline, PipelineHandler};
|
||||||
use middleware::Middleware;
|
use middleware::Middleware;
|
||||||
use server::ServerSettings;
|
use server::{HttpHandler, IntoHttpHandler, HttpHandlerTask, ServerSettings};
|
||||||
|
|
||||||
/// Application
|
/// Application
|
||||||
pub struct HttpApplication<S=()> {
|
pub struct HttpApplication<S=()> {
|
||||||
|
15
src/lib.rs
15
src/lib.rs
@ -104,13 +104,6 @@ mod param;
|
|||||||
mod resource;
|
mod resource;
|
||||||
mod handler;
|
mod handler;
|
||||||
mod pipeline;
|
mod pipeline;
|
||||||
mod server;
|
|
||||||
mod worker;
|
|
||||||
mod channel;
|
|
||||||
mod h1;
|
|
||||||
mod h2;
|
|
||||||
mod h1writer;
|
|
||||||
mod h2writer;
|
|
||||||
|
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
pub mod ws;
|
pub mod ws;
|
||||||
@ -121,17 +114,18 @@ pub mod middleware;
|
|||||||
pub mod pred;
|
pub mod pred;
|
||||||
pub mod test;
|
pub mod test;
|
||||||
pub mod payload;
|
pub mod payload;
|
||||||
|
pub mod server;
|
||||||
pub use error::{Error, Result, ResponseError};
|
pub use error::{Error, Result, ResponseError};
|
||||||
pub use body::{Body, Binary};
|
pub use body::{Body, Binary};
|
||||||
pub use json::{Json};
|
pub use json::Json;
|
||||||
pub use application::Application;
|
pub use application::Application;
|
||||||
pub use httprequest::HttpRequest;
|
pub use httprequest::HttpRequest;
|
||||||
pub use httpresponse::HttpResponse;
|
pub use httpresponse::HttpResponse;
|
||||||
pub use handler::{Reply, Responder, NormalizePath, AsyncResponder};
|
pub use handler::{Reply, Responder, NormalizePath, AsyncResponder};
|
||||||
pub use route::Route;
|
pub use route::Route;
|
||||||
pub use resource::Resource;
|
pub use resource::Resource;
|
||||||
pub use server::HttpServer;
|
|
||||||
pub use context::HttpContext;
|
pub use context::HttpContext;
|
||||||
|
pub use server::HttpServer;
|
||||||
|
|
||||||
// re-exports
|
// re-exports
|
||||||
pub use http::{Method, StatusCode, Version};
|
pub use http::{Method, StatusCode, Version};
|
||||||
@ -171,10 +165,7 @@ pub mod dev {
|
|||||||
pub use handler::Handler;
|
pub use handler::Handler;
|
||||||
pub use json::JsonBody;
|
pub use json::JsonBody;
|
||||||
pub use router::{Router, Pattern};
|
pub use router::{Router, Pattern};
|
||||||
pub use channel::{HttpChannel, HttpHandler, IntoHttpHandler};
|
|
||||||
pub use param::{FromParam, Params};
|
pub use param::{FromParam, Params};
|
||||||
pub use httprequest::{UrlEncoded, RequestBody};
|
pub use httprequest::{UrlEncoded, RequestBody};
|
||||||
pub use httpresponse::HttpResponseBuilder;
|
pub use httpresponse::HttpResponseBuilder;
|
||||||
|
|
||||||
pub use server::{ServerSettings, PauseServer, ResumeServer, StopServer};
|
|
||||||
}
|
}
|
||||||
|
@ -6,16 +6,15 @@ use std::marker::PhantomData;
|
|||||||
use futures::{Async, Poll, Future, Stream};
|
use futures::{Async, Poll, Future, Stream};
|
||||||
use futures::unsync::oneshot;
|
use futures::unsync::oneshot;
|
||||||
|
|
||||||
use channel::HttpHandlerTask;
|
|
||||||
use body::{Body, BodyStream};
|
use body::{Body, BodyStream};
|
||||||
use context::{Frame, ActorHttpContext};
|
use context::{Frame, ActorHttpContext};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use handler::{Reply, ReplyItem};
|
use handler::{Reply, ReplyItem};
|
||||||
use h1writer::{Writer, WriterState};
|
|
||||||
use httprequest::HttpRequest;
|
use httprequest::HttpRequest;
|
||||||
use httpresponse::HttpResponse;
|
use httpresponse::HttpResponse;
|
||||||
use middleware::{Middleware, Finished, Started, Response};
|
use middleware::{Middleware, Finished, Started, Response};
|
||||||
use application::Inner;
|
use application::Inner;
|
||||||
|
use server::{Writer, WriterState, HttpHandlerTask};
|
||||||
|
|
||||||
pub(crate) trait PipelineHandler<S> {
|
pub(crate) trait PipelineHandler<S> {
|
||||||
fn handle(&mut self, req: HttpRequest<S>) -> Reply;
|
fn handle(&mut self, req: HttpRequest<S>) -> Reply;
|
||||||
|
@ -7,49 +7,10 @@ use futures::{Future, Poll, Async};
|
|||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio_core::net::TcpStream;
|
use tokio_core::net::TcpStream;
|
||||||
|
|
||||||
use {h1, h2};
|
use super::{h1, h2, HttpHandler, IoStream};
|
||||||
use error::Error;
|
use super::settings::WorkerSettings;
|
||||||
use h1writer::Writer;
|
|
||||||
use httprequest::HttpRequest;
|
|
||||||
use server::ServerSettings;
|
|
||||||
use worker::WorkerSettings;
|
|
||||||
|
|
||||||
/// Low level http request handler
|
enum HttpProtocol<T: IoStream, H: 'static> {
|
||||||
#[allow(unused_variables)]
|
|
||||||
pub trait HttpHandler: 'static {
|
|
||||||
|
|
||||||
/// Handle request
|
|
||||||
fn handle(&mut self, req: HttpRequest) -> Result<Box<HttpHandlerTask>, HttpRequest>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait HttpHandlerTask {
|
|
||||||
|
|
||||||
fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error>;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<(), Error>;
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum HttpProtocol<T: IoStream, H: 'static>
|
|
||||||
{
|
|
||||||
H1(h1::Http1<T, H>),
|
H1(h1::Http1<T, H>),
|
||||||
H2(h2::Http2<T, H>),
|
H2(h2::Http2<T, H>),
|
||||||
}
|
}
|
||||||
@ -247,16 +208,6 @@ impl Node<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 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 {
|
impl IoStream for TcpStream {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn shutdown(&mut self, how: Shutdown) -> io::Result<()> {
|
fn shutdown(&mut self, how: Shutdown) -> io::Result<()> {
|
@ -14,14 +14,16 @@ use tokio_core::reactor::Timeout;
|
|||||||
|
|
||||||
use pipeline::Pipeline;
|
use pipeline::Pipeline;
|
||||||
use encoding::PayloadType;
|
use encoding::PayloadType;
|
||||||
use channel::{HttpHandler, HttpHandlerTask, IoStream};
|
|
||||||
use h1writer::{Writer, H1Writer};
|
|
||||||
use worker::WorkerSettings;
|
|
||||||
use httpcodes::HTTPNotFound;
|
use httpcodes::HTTPNotFound;
|
||||||
use httprequest::HttpRequest;
|
use httprequest::HttpRequest;
|
||||||
use error::{ParseError, PayloadError, ResponseError};
|
use error::{ParseError, PayloadError, ResponseError};
|
||||||
use payload::{Payload, PayloadWriter, DEFAULT_BUFFER_SIZE};
|
use payload::{Payload, PayloadWriter, DEFAULT_BUFFER_SIZE};
|
||||||
|
|
||||||
|
use super::Writer;
|
||||||
|
use super::h1writer::H1Writer;
|
||||||
|
use super::settings::WorkerSettings;
|
||||||
|
use super::{HttpHandler, HttpHandlerTask, IoStream};
|
||||||
|
|
||||||
const LW_BUFFER_SIZE: usize = 4096;
|
const LW_BUFFER_SIZE: usize = 4096;
|
||||||
const HW_BUFFER_SIZE: usize = 16_384;
|
const HW_BUFFER_SIZE: usize = 16_384;
|
||||||
const MAX_BUFFER_SIZE: usize = 131_072;
|
const MAX_BUFFER_SIZE: usize = 131_072;
|
||||||
@ -901,8 +903,8 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use application::HttpApplication;
|
use application::HttpApplication;
|
||||||
use worker::WorkerSettings;
|
use server::settings::WorkerSettings;
|
||||||
use channel::IoStream;
|
use server::IoStream;
|
||||||
|
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
buf: Bytes,
|
buf: Bytes,
|
@ -11,32 +11,9 @@ use helpers::SharedBytes;
|
|||||||
use encoding::PayloadEncoder;
|
use encoding::PayloadEncoder;
|
||||||
use httprequest::HttpMessage;
|
use httprequest::HttpMessage;
|
||||||
use httpresponse::HttpResponse;
|
use httpresponse::HttpResponse;
|
||||||
|
use server::{Writer, WriterState, MAX_WRITE_BUFFER_SIZE};
|
||||||
|
|
||||||
const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific
|
const AVERAGE_HEADER_SIZE: usize = 30; // totally scientific
|
||||||
const MAX_WRITE_BUFFER_SIZE: usize = 65_536; // max buffer size 64k
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum WriterState {
|
|
||||||
Done,
|
|
||||||
Pause,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Send stream
|
|
||||||
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>;
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
struct Flags: u8 {
|
struct Flags: u8 {
|
@ -15,15 +15,16 @@ use tokio_io::{AsyncRead, AsyncWrite};
|
|||||||
use tokio_core::reactor::Timeout;
|
use tokio_core::reactor::Timeout;
|
||||||
|
|
||||||
use pipeline::Pipeline;
|
use pipeline::Pipeline;
|
||||||
use h2writer::H2Writer;
|
|
||||||
use worker::WorkerSettings;
|
|
||||||
use channel::{HttpHandler, HttpHandlerTask};
|
|
||||||
use error::PayloadError;
|
use error::PayloadError;
|
||||||
use encoding::PayloadType;
|
use encoding::PayloadType;
|
||||||
use httpcodes::HTTPNotFound;
|
use httpcodes::HTTPNotFound;
|
||||||
use httprequest::HttpRequest;
|
use httprequest::HttpRequest;
|
||||||
use payload::{Payload, PayloadWriter};
|
use payload::{Payload, PayloadWriter};
|
||||||
|
|
||||||
|
use super::h2writer::H2Writer;
|
||||||
|
use super::settings::WorkerSettings;
|
||||||
|
use super::{HttpHandler, HttpHandlerTask};
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
struct Flags: u8 {
|
struct Flags: u8 {
|
||||||
const DISCONNECTED = 0b0000_0010;
|
const DISCONNECTED = 0b0000_0010;
|
@ -12,10 +12,9 @@ use helpers::SharedBytes;
|
|||||||
use encoding::PayloadEncoder;
|
use encoding::PayloadEncoder;
|
||||||
use httprequest::HttpMessage;
|
use httprequest::HttpMessage;
|
||||||
use httpresponse::HttpResponse;
|
use httpresponse::HttpResponse;
|
||||||
use h1writer::{Writer, WriterState};
|
use server::{Writer, WriterState, MAX_WRITE_BUFFER_SIZE};
|
||||||
|
|
||||||
const CHUNK_SIZE: usize = 16_384;
|
const CHUNK_SIZE: usize = 16_384;
|
||||||
const MAX_WRITE_BUFFER_SIZE: usize = 65_536; // max buffer size 64k
|
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
struct Flags: u8 {
|
struct Flags: u8 {
|
109
src/server/mod.rs
Normal file
109
src/server/mod.rs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
//! Http server
|
||||||
|
use std::{time, io};
|
||||||
|
use std::net::Shutdown;
|
||||||
|
|
||||||
|
use futures::Poll;
|
||||||
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
|
|
||||||
|
mod srv;
|
||||||
|
mod worker;
|
||||||
|
mod channel;
|
||||||
|
mod h1;
|
||||||
|
mod h2;
|
||||||
|
mod h1writer;
|
||||||
|
mod h2writer;
|
||||||
|
mod settings;
|
||||||
|
|
||||||
|
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>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait HttpHandlerTask {
|
||||||
|
|
||||||
|
fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error>;
|
||||||
|
|
||||||
|
fn poll(&mut self) -> Poll<(), Error>;
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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>;
|
||||||
|
}
|
125
src/server/settings.rs
Normal file
125
src/server/settings.rs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
use std::net;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::cell::{Cell, RefCell, RefMut};
|
||||||
|
|
||||||
|
use helpers;
|
||||||
|
use super::channel::Node;
|
||||||
|
|
||||||
|
/// Various server settings
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ServerSettings {
|
||||||
|
addr: Option<net::SocketAddr>,
|
||||||
|
secure: bool,
|
||||||
|
host: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ServerSettings {
|
||||||
|
fn default() -> Self {
|
||||||
|
ServerSettings {
|
||||||
|
addr: None,
|
||||||
|
secure: false,
|
||||||
|
host: "localhost:8080".to_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ServerSettings {
|
||||||
|
/// Crate server settings instance
|
||||||
|
pub(crate) fn new(addr: Option<net::SocketAddr>, host: &Option<String>, secure: bool)
|
||||||
|
-> ServerSettings
|
||||||
|
{
|
||||||
|
let host = if let Some(ref host) = *host {
|
||||||
|
host.clone()
|
||||||
|
} else if let Some(ref addr) = addr {
|
||||||
|
format!("{}", addr)
|
||||||
|
} else {
|
||||||
|
"localhost".to_owned()
|
||||||
|
};
|
||||||
|
ServerSettings {
|
||||||
|
addr: addr,
|
||||||
|
secure: secure,
|
||||||
|
host: host,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the socket address of the local half of this TCP connection
|
||||||
|
pub fn local_addr(&self) -> Option<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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub(crate) struct WorkerSettings<H> {
|
||||||
|
h: RefCell<Vec<H>>,
|
||||||
|
enabled: bool,
|
||||||
|
keep_alive: u64,
|
||||||
|
bytes: Rc<helpers::SharedBytesPool>,
|
||||||
|
messages: Rc<helpers::SharedMessagePool>,
|
||||||
|
channels: Cell<usize>,
|
||||||
|
node: Node<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H> WorkerSettings<H> {
|
||||||
|
pub(crate) fn new(h: Vec<H>, keep_alive: Option<u64>) -> WorkerSettings<H> {
|
||||||
|
WorkerSettings {
|
||||||
|
h: RefCell::new(h),
|
||||||
|
enabled: if let Some(ka) = keep_alive { ka > 0 } else { false },
|
||||||
|
keep_alive: keep_alive.unwrap_or(0),
|
||||||
|
bytes: Rc::new(helpers::SharedBytesPool::new()),
|
||||||
|
messages: Rc::new(helpers::SharedMessagePool::new()),
|
||||||
|
channels: Cell::new(0),
|
||||||
|
node: Node::head(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn num_channels(&self) -> usize {
|
||||||
|
self.channels.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn head(&self) -> &Node<()> {
|
||||||
|
&self.node
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handlers(&self) -> RefMut<Vec<H>> {
|
||||||
|
self.h.borrow_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn keep_alive(&self) -> u64 {
|
||||||
|
self.keep_alive
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn keep_alive_enabled(&self) -> bool {
|
||||||
|
self.enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_shared_bytes(&self) -> helpers::SharedBytes {
|
||||||
|
helpers::SharedBytes::new(self.bytes.get_bytes(), Rc::clone(&self.bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_http_message(&self) -> helpers::SharedHttpMessage {
|
||||||
|
helpers::SharedHttpMessage::new(self.messages.get(), Rc::clone(&self.messages))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_channel(&self) {
|
||||||
|
self.channels.set(self.channels.get() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_channel(&self) {
|
||||||
|
let num = self.channels.get();
|
||||||
|
if num > 0 {
|
||||||
|
self.channels.set(num-1);
|
||||||
|
} else {
|
||||||
|
error!("Number of removed channels is bigger than added channel. Bug in actix-web");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,59 +28,12 @@ use openssl::pkcs12::ParsedPkcs12;
|
|||||||
use tokio_openssl::SslStream;
|
use tokio_openssl::SslStream;
|
||||||
|
|
||||||
use helpers;
|
use helpers;
|
||||||
use channel::{HttpChannel, HttpHandler, IntoHttpHandler, IoStream, WrapperStream};
|
use super::{HttpHandler, IntoHttpHandler, IoStream};
|
||||||
use worker::{Conn, Worker, WorkerSettings, StreamHandlerType, StopWorker};
|
use super::{PauseServer, ResumeServer, StopServer};
|
||||||
|
use super::channel::{HttpChannel, WrapperStream};
|
||||||
|
use super::worker::{Conn, Worker, StreamHandlerType, StopWorker};
|
||||||
|
use super::settings::{ServerSettings, WorkerSettings};
|
||||||
|
|
||||||
/// Various server settings
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct ServerSettings {
|
|
||||||
addr: Option<net::SocketAddr>,
|
|
||||||
secure: bool,
|
|
||||||
host: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for ServerSettings {
|
|
||||||
fn default() -> Self {
|
|
||||||
ServerSettings {
|
|
||||||
addr: None,
|
|
||||||
secure: false,
|
|
||||||
host: "localhost:8080".to_owned(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ServerSettings {
|
|
||||||
/// Crate server settings instance
|
|
||||||
fn new(addr: Option<net::SocketAddr>, host: &Option<String>, secure: bool) -> Self {
|
|
||||||
let host = if let Some(ref host) = *host {
|
|
||||||
host.clone()
|
|
||||||
} else if let Some(ref addr) = addr {
|
|
||||||
format!("{}", addr)
|
|
||||||
} else {
|
|
||||||
"localhost".to_owned()
|
|
||||||
};
|
|
||||||
ServerSettings {
|
|
||||||
addr: addr,
|
|
||||||
secure: secure,
|
|
||||||
host: host,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the socket address of the local half of this TCP connection
|
|
||||||
pub fn local_addr(&self) -> Option<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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An HTTP Server
|
/// An HTTP Server
|
||||||
///
|
///
|
||||||
@ -585,25 +538,6 @@ impl<T, A, H, U, V> Handler<io::Result<Conn<T>>> for HttpServer<T, A, H, U>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, A, H, U, V> Handler<PauseServer> for HttpServer<T, A, H, U>
|
impl<T, A, H, U, V> Handler<PauseServer> for HttpServer<T, A, H, U>
|
||||||
where T: IoStream,
|
where T: IoStream,
|
||||||
H: HttpHandler + 'static,
|
H: HttpHandler + 'static,
|
@ -1,6 +1,5 @@
|
|||||||
use std::{net, time};
|
use std::{net, time};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::cell::{Cell, RefCell, RefMut};
|
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use futures::unsync::oneshot;
|
use futures::unsync::oneshot;
|
||||||
use tokio_core::net::TcpStream;
|
use tokio_core::net::TcpStream;
|
||||||
@ -25,7 +24,9 @@ use actix::*;
|
|||||||
use actix::msgs::StopArbiter;
|
use actix::msgs::StopArbiter;
|
||||||
|
|
||||||
use helpers;
|
use helpers;
|
||||||
use channel::{HttpChannel, HttpHandler, Node};
|
use server::HttpHandler;
|
||||||
|
use server::channel::HttpChannel;
|
||||||
|
use server::settings::WorkerSettings;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Message)]
|
#[derive(Message)]
|
||||||
@ -43,60 +44,6 @@ pub(crate) struct StopWorker {
|
|||||||
pub graceful: Option<time::Duration>,
|
pub graceful: Option<time::Duration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct WorkerSettings<H> {
|
|
||||||
h: RefCell<Vec<H>>,
|
|
||||||
enabled: bool,
|
|
||||||
keep_alive: u64,
|
|
||||||
bytes: Rc<helpers::SharedBytesPool>,
|
|
||||||
messages: Rc<helpers::SharedMessagePool>,
|
|
||||||
channels: Cell<usize>,
|
|
||||||
node: Node<()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<H> WorkerSettings<H> {
|
|
||||||
pub(crate) fn new(h: Vec<H>, keep_alive: Option<u64>) -> WorkerSettings<H> {
|
|
||||||
WorkerSettings {
|
|
||||||
h: RefCell::new(h),
|
|
||||||
enabled: if let Some(ka) = keep_alive { ka > 0 } else { false },
|
|
||||||
keep_alive: keep_alive.unwrap_or(0),
|
|
||||||
bytes: Rc::new(helpers::SharedBytesPool::new()),
|
|
||||||
messages: Rc::new(helpers::SharedMessagePool::new()),
|
|
||||||
channels: Cell::new(0),
|
|
||||||
node: Node::head(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn head(&self) -> &Node<()> {
|
|
||||||
&self.node
|
|
||||||
}
|
|
||||||
pub fn handlers(&self) -> RefMut<Vec<H>> {
|
|
||||||
self.h.borrow_mut()
|
|
||||||
}
|
|
||||||
pub fn keep_alive(&self) -> u64 {
|
|
||||||
self.keep_alive
|
|
||||||
}
|
|
||||||
pub fn keep_alive_enabled(&self) -> bool {
|
|
||||||
self.enabled
|
|
||||||
}
|
|
||||||
pub fn get_shared_bytes(&self) -> helpers::SharedBytes {
|
|
||||||
helpers::SharedBytes::new(self.bytes.get_bytes(), Rc::clone(&self.bytes))
|
|
||||||
}
|
|
||||||
pub fn get_http_message(&self) -> helpers::SharedHttpMessage {
|
|
||||||
helpers::SharedHttpMessage::new(self.messages.get(), Rc::clone(&self.messages))
|
|
||||||
}
|
|
||||||
pub fn add_channel(&self) {
|
|
||||||
self.channels.set(self.channels.get()+1);
|
|
||||||
}
|
|
||||||
pub fn remove_channel(&self) {
|
|
||||||
let num = self.channels.get();
|
|
||||||
if num > 0 {
|
|
||||||
self.channels.set(num-1);
|
|
||||||
} else {
|
|
||||||
error!("Number of removed channels is bigger than added channel. Bug in actix-web");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Http worker
|
/// Http worker
|
||||||
///
|
///
|
||||||
/// Worker accepts Socket objects via unbounded channel and start requests processing.
|
/// Worker accepts Socket objects via unbounded channel and start requests processing.
|
||||||
@ -127,7 +74,7 @@ impl<H: HttpHandler + 'static> Worker<H> {
|
|||||||
tx: oneshot::Sender<bool>, dur: time::Duration) {
|
tx: oneshot::Sender<bool>, dur: time::Duration) {
|
||||||
// sleep for 1 second and then check again
|
// sleep for 1 second and then check again
|
||||||
ctx.run_later(time::Duration::new(1, 0), move |slf, ctx| {
|
ctx.run_later(time::Duration::new(1, 0), move |slf, ctx| {
|
||||||
let num = slf.settings.channels.get();
|
let num = slf.settings.num_channels();
|
||||||
if num == 0 {
|
if num == 0 {
|
||||||
let _ = tx.send(true);
|
let _ = tx.send(true);
|
||||||
Arbiter::arbiter().send(StopArbiter(0));
|
Arbiter::arbiter().send(StopArbiter(0));
|
||||||
@ -174,7 +121,7 @@ impl<H> Handler<StopWorker> for Worker<H>
|
|||||||
type Result = Response<Self, StopWorker>;
|
type Result = Response<Self, StopWorker>;
|
||||||
|
|
||||||
fn handle(&mut self, msg: StopWorker, ctx: &mut Context<Self>) -> Self::Result {
|
fn handle(&mut self, msg: StopWorker, ctx: &mut Context<Self>) -> Self::Result {
|
||||||
let num = self.settings.channels.get();
|
let num = self.settings.num_channels();
|
||||||
if num == 0 {
|
if num == 0 {
|
||||||
info!("Shutting down http worker, 0 connections");
|
info!("Shutting down http worker, 0 connections");
|
||||||
Self::reply(Ok(true))
|
Self::reply(Ok(true))
|
@ -16,9 +16,7 @@ use tokio_core::reactor::Core;
|
|||||||
use net2::TcpBuilder;
|
use net2::TcpBuilder;
|
||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use server::{HttpServer, ServerSettings};
|
|
||||||
use handler::{Handler, Responder, ReplyItem};
|
use handler::{Handler, Responder, ReplyItem};
|
||||||
use channel::{HttpHandler, IntoHttpHandler};
|
|
||||||
use middleware::Middleware;
|
use middleware::Middleware;
|
||||||
use application::{Application, HttpApplication};
|
use application::{Application, HttpApplication};
|
||||||
use param::Params;
|
use param::Params;
|
||||||
@ -26,6 +24,7 @@ use router::Router;
|
|||||||
use payload::Payload;
|
use payload::Payload;
|
||||||
use httprequest::HttpRequest;
|
use httprequest::HttpRequest;
|
||||||
use httpresponse::HttpResponse;
|
use httpresponse::HttpResponse;
|
||||||
|
use server::{HttpServer, HttpHandler, IntoHttpHandler, ServerSettings};
|
||||||
|
|
||||||
/// The `TestServer` type.
|
/// The `TestServer` type.
|
||||||
///
|
///
|
||||||
|
@ -72,12 +72,12 @@ fn test_start() {
|
|||||||
assert!(reqwest::get(&format!("http://{}/", addr)).unwrap().status().is_success());
|
assert!(reqwest::get(&format!("http://{}/", addr)).unwrap().status().is_success());
|
||||||
|
|
||||||
// pause
|
// pause
|
||||||
let _ = srv_addr.call_fut(dev::PauseServer).wait();
|
let _ = srv_addr.call_fut(server::PauseServer).wait();
|
||||||
thread::sleep(time::Duration::from_millis(100));
|
thread::sleep(time::Duration::from_millis(100));
|
||||||
assert!(net::TcpStream::connect(addr).is_err());
|
assert!(net::TcpStream::connect(addr).is_err());
|
||||||
|
|
||||||
// resume
|
// resume
|
||||||
let _ = srv_addr.call_fut(dev::ResumeServer).wait();
|
let _ = srv_addr.call_fut(server::ResumeServer).wait();
|
||||||
assert!(reqwest::get(&format!("http://{}/", addr)).unwrap().status().is_success());
|
assert!(reqwest::get(&format!("http://{}/", addr)).unwrap().status().is_success());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user