mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-30 10:42:55 +01:00
refactor http service builder
This commit is contained in:
parent
0aa0f326f7
commit
9f1417af30
@ -61,6 +61,7 @@ flate2-rust = ["flate2/rust_backend"]
|
||||
[dependencies]
|
||||
actix = "0.7.0"
|
||||
actix-net = { git="https://github.com/actix/actix-net.git" }
|
||||
#actix-net = { path = "../actix-net" }
|
||||
|
||||
base64 = "0.9"
|
||||
bitflags = "1.0"
|
||||
|
@ -1127,12 +1127,23 @@ mod tests {
|
||||
let resp: HttpResponse = HttpResponse::Ok().into();
|
||||
let resp = cors.response(&req, resp).unwrap().response();
|
||||
|
||||
let origins_str = resp.headers().get(header::ACCESS_CONTROL_ALLOW_ORIGIN).unwrap().to_str().unwrap();
|
||||
let origins_str = resp
|
||||
.headers()
|
||||
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap();
|
||||
|
||||
if origins_str.starts_with("https://www.example.com") {
|
||||
assert_eq!("https://www.example.com, https://www.google.com", origins_str);
|
||||
assert_eq!(
|
||||
"https://www.example.com, https://www.google.com",
|
||||
origins_str
|
||||
);
|
||||
} else {
|
||||
assert_eq!("https://www.google.com, https://www.example.com", origins_str);
|
||||
assert_eq!(
|
||||
"https://www.google.com, https://www.example.com",
|
||||
origins_str
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
//! Payload stream
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::task::Task;
|
||||
#[cfg(not(test))]
|
||||
use futures::task::current as current_task;
|
||||
use futures::task::Task;
|
||||
use futures::{Async, Poll, Stream};
|
||||
use std::cell::RefCell;
|
||||
use std::cmp;
|
||||
|
257
src/server/builder.rs
Normal file
257
src/server/builder.rs
Normal file
@ -0,0 +1,257 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::net;
|
||||
|
||||
use actix_net::server;
|
||||
use actix_net::service::{NewService, NewServiceExt, Service};
|
||||
use futures::future::{ok, FutureResult};
|
||||
use futures::{Async, Poll};
|
||||
use tokio_tcp::TcpStream;
|
||||
|
||||
use super::handler::IntoHttpHandler;
|
||||
use super::service::HttpService;
|
||||
use super::{IoStream, KeepAlive};
|
||||
|
||||
pub(crate) trait ServiceFactory<H>
|
||||
where
|
||||
H: IntoHttpHandler,
|
||||
{
|
||||
fn register(&self, server: server::Server, lst: net::TcpListener) -> server::Server;
|
||||
}
|
||||
|
||||
pub struct HttpServiceBuilder<F, H, A, P>
|
||||
where
|
||||
F: Fn() -> H + Send + Clone,
|
||||
{
|
||||
factory: F,
|
||||
acceptor: A,
|
||||
pipeline: P,
|
||||
}
|
||||
|
||||
impl<F, H, A, P> HttpServiceBuilder<F, H, A, P>
|
||||
where
|
||||
F: Fn() -> H + Send + Clone,
|
||||
H: IntoHttpHandler,
|
||||
A: AcceptorServiceFactory,
|
||||
P: HttpPipelineFactory<Io = A::Io>,
|
||||
{
|
||||
pub fn new(factory: F, acceptor: A, pipeline: P) -> Self {
|
||||
Self {
|
||||
factory,
|
||||
pipeline,
|
||||
acceptor,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn acceptor<A1>(self, acceptor: A1) -> HttpServiceBuilder<F, H, A1, P>
|
||||
where
|
||||
A1: AcceptorServiceFactory,
|
||||
{
|
||||
HttpServiceBuilder {
|
||||
acceptor,
|
||||
pipeline: self.pipeline,
|
||||
factory: self.factory.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pipeline<P1>(self, pipeline: P1) -> HttpServiceBuilder<F, H, A, P1>
|
||||
where
|
||||
P1: HttpPipelineFactory,
|
||||
{
|
||||
HttpServiceBuilder {
|
||||
pipeline,
|
||||
acceptor: self.acceptor,
|
||||
factory: self.factory.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn finish(&self) -> impl server::StreamServiceFactory {
|
||||
let pipeline = self.pipeline.clone();
|
||||
let acceptor = self.acceptor.clone();
|
||||
move || acceptor.create().and_then(pipeline.create())
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, H, A, P> Clone for HttpServiceBuilder<F, H, A, P>
|
||||
where
|
||||
F: Fn() -> H + Send + Clone,
|
||||
A: AcceptorServiceFactory,
|
||||
P: HttpPipelineFactory<Io = A::Io>,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
HttpServiceBuilder {
|
||||
factory: self.factory.clone(),
|
||||
acceptor: self.acceptor.clone(),
|
||||
pipeline: self.pipeline.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, H, A, P> ServiceFactory<H> for HttpServiceBuilder<F, H, A, P>
|
||||
where
|
||||
F: Fn() -> H + Send + Clone,
|
||||
A: AcceptorServiceFactory,
|
||||
P: HttpPipelineFactory<Io = A::Io>,
|
||||
H: IntoHttpHandler,
|
||||
{
|
||||
fn register(&self, server: server::Server, lst: net::TcpListener) -> server::Server {
|
||||
server.listen("actix-web", lst, self.finish())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AcceptorServiceFactory: Send + Clone + 'static {
|
||||
type Io: IoStream + Send;
|
||||
type NewService: NewService<
|
||||
Request = TcpStream,
|
||||
Response = Self::Io,
|
||||
Error = (),
|
||||
InitError = (),
|
||||
>;
|
||||
|
||||
fn create(&self) -> Self::NewService;
|
||||
}
|
||||
|
||||
impl<F, T> AcceptorServiceFactory for F
|
||||
where
|
||||
F: Fn() -> T + Send + Clone + 'static,
|
||||
T::Response: IoStream + Send,
|
||||
T: NewService<Request = TcpStream, Error = (), InitError = ()>,
|
||||
{
|
||||
type Io = T::Response;
|
||||
type NewService = T;
|
||||
|
||||
fn create(&self) -> T {
|
||||
(self)()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HttpPipelineFactory: Send + Clone + 'static {
|
||||
type Io: IoStream;
|
||||
type NewService: NewService<
|
||||
Request = Self::Io,
|
||||
Response = (),
|
||||
Error = (),
|
||||
InitError = (),
|
||||
>;
|
||||
|
||||
fn create(&self) -> Self::NewService;
|
||||
}
|
||||
|
||||
impl<F, T> HttpPipelineFactory for F
|
||||
where
|
||||
F: Fn() -> T + Send + Clone + 'static,
|
||||
T: NewService<Response = (), Error = (), InitError = ()>,
|
||||
T::Request: IoStream,
|
||||
{
|
||||
type Io = T::Request;
|
||||
type NewService = T;
|
||||
|
||||
fn create(&self) -> T {
|
||||
(self)()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct DefaultPipelineFactory<F, H, Io>
|
||||
where
|
||||
F: Fn() -> H + Send + Clone,
|
||||
{
|
||||
factory: F,
|
||||
host: Option<String>,
|
||||
addr: net::SocketAddr,
|
||||
keep_alive: KeepAlive,
|
||||
_t: PhantomData<Io>,
|
||||
}
|
||||
|
||||
impl<F, H, Io> DefaultPipelineFactory<F, H, Io>
|
||||
where
|
||||
Io: IoStream + Send,
|
||||
F: Fn() -> H + Send + Clone + 'static,
|
||||
H: IntoHttpHandler + 'static,
|
||||
{
|
||||
pub fn new(
|
||||
factory: F, host: Option<String>, addr: net::SocketAddr, keep_alive: KeepAlive,
|
||||
) -> Self {
|
||||
Self {
|
||||
factory,
|
||||
addr,
|
||||
keep_alive,
|
||||
host,
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, H, Io> Clone for DefaultPipelineFactory<F, H, Io>
|
||||
where
|
||||
Io: IoStream,
|
||||
F: Fn() -> H + Send + Clone,
|
||||
H: IntoHttpHandler,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
factory: self.factory.clone(),
|
||||
addr: self.addr,
|
||||
keep_alive: self.keep_alive,
|
||||
host: self.host.clone(),
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, H, Io> HttpPipelineFactory for DefaultPipelineFactory<F, H, Io>
|
||||
where
|
||||
Io: IoStream + Send,
|
||||
F: Fn() -> H + Send + Clone + 'static,
|
||||
H: IntoHttpHandler + 'static,
|
||||
{
|
||||
type Io = Io;
|
||||
type NewService = HttpService<F, H, Io>;
|
||||
|
||||
fn create(&self) -> Self::NewService {
|
||||
HttpService::new(
|
||||
self.factory.clone(),
|
||||
self.addr,
|
||||
self.host.clone(),
|
||||
self.keep_alive,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct DefaultAcceptor;
|
||||
|
||||
impl AcceptorServiceFactory for DefaultAcceptor {
|
||||
type Io = TcpStream;
|
||||
type NewService = DefaultAcceptor;
|
||||
|
||||
fn create(&self) -> Self::NewService {
|
||||
DefaultAcceptor
|
||||
}
|
||||
}
|
||||
|
||||
impl NewService for DefaultAcceptor {
|
||||
type Request = TcpStream;
|
||||
type Response = TcpStream;
|
||||
type Error = ();
|
||||
type InitError = ();
|
||||
type Service = DefaultAcceptor;
|
||||
type Future = FutureResult<Self::Service, Self::InitError>;
|
||||
|
||||
fn new_service(&self) -> Self::Future {
|
||||
ok(DefaultAcceptor)
|
||||
}
|
||||
}
|
||||
|
||||
impl Service for DefaultAcceptor {
|
||||
type Request = TcpStream;
|
||||
type Response = TcpStream;
|
||||
type Error = ();
|
||||
type Future = FutureResult<Self::Response, Self::Error>;
|
||||
|
||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||
Ok(Async::Ready(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, req: Self::Request) -> Self::Future {
|
||||
ok(req)
|
||||
}
|
||||
}
|
@ -89,8 +89,8 @@ where
|
||||
H: HttpHandler + 'static,
|
||||
{
|
||||
pub fn new(
|
||||
settings: WorkerSettings<H>, stream: T, addr: Option<SocketAddr>,
|
||||
buf: BytesMut, is_eof: bool, keepalive_timer: Option<Delay>,
|
||||
settings: WorkerSettings<H>, stream: T, addr: Option<SocketAddr>, buf: BytesMut,
|
||||
is_eof: bool, keepalive_timer: Option<Delay>,
|
||||
) -> Self {
|
||||
Http1 {
|
||||
flags: if is_eof {
|
||||
@ -379,10 +379,7 @@ where
|
||||
|
||||
fn push_response_entry(&mut self, status: StatusCode) {
|
||||
self.tasks.push_back(Entry {
|
||||
pipe: EntryPipe::Error(ServerError::err(
|
||||
Version::HTTP_11,
|
||||
status,
|
||||
)),
|
||||
pipe: EntryPipe::Error(ServerError::err(Version::HTTP_11, status)),
|
||||
flags: EntryFlags::empty(),
|
||||
});
|
||||
}
|
||||
|
@ -1,13 +1,10 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::{io, mem, net, time};
|
||||
use std::{io, mem, net};
|
||||
|
||||
use actix::{Actor, Addr, AsyncContext, Context, Handler, System};
|
||||
use actix_net::server::{Server, ServerServiceFactory};
|
||||
use actix_net::service::{NewService, NewServiceExt, Service};
|
||||
use actix::{Addr, System};
|
||||
use actix_net::server;
|
||||
use actix_net::service::NewService;
|
||||
use actix_net::ssl;
|
||||
|
||||
use futures::future::{ok, FutureResult};
|
||||
use futures::{Async, Poll, Stream};
|
||||
use net2::TcpBuilder;
|
||||
use num_cpus;
|
||||
use tokio_tcp::TcpStream;
|
||||
@ -21,9 +18,9 @@ use openssl::ssl::SslAcceptorBuilder;
|
||||
//#[cfg(feature = "rust-tls")]
|
||||
//use rustls::ServerConfig;
|
||||
|
||||
use super::channel::HttpChannel;
|
||||
use super::settings::{ServerSettings, WorkerSettings};
|
||||
use super::{HttpHandler, IntoHttpHandler, IoStream, KeepAlive};
|
||||
use super::builder::{AcceptorServiceFactory, HttpServiceBuilder, ServiceFactory};
|
||||
use super::builder::{DefaultAcceptor, DefaultPipelineFactory};
|
||||
use super::{IntoHttpHandler, IoStream, KeepAlive};
|
||||
|
||||
struct Socket<H: IntoHttpHandler> {
|
||||
scheme: &'static str,
|
||||
@ -205,17 +202,16 @@ where
|
||||
lst,
|
||||
addr,
|
||||
scheme: "http",
|
||||
handler: Box::new(SimpleFactory {
|
||||
handler: Box::new(HttpServiceBuilder::new(
|
||||
self.factory.clone(),
|
||||
DefaultAcceptor,
|
||||
DefaultPipelineFactory::new(
|
||||
self.factory.clone(),
|
||||
self.host.clone(),
|
||||
addr,
|
||||
factory: self.factory.clone(),
|
||||
pipeline: DefaultPipelineFactory {
|
||||
addr,
|
||||
factory: self.factory.clone(),
|
||||
host: self.host.clone(),
|
||||
keep_alive: self.keep_alive,
|
||||
_t: PhantomData,
|
||||
},
|
||||
}),
|
||||
self.keep_alive,
|
||||
),
|
||||
)),
|
||||
});
|
||||
|
||||
self
|
||||
@ -239,6 +235,7 @@ where
|
||||
addr,
|
||||
scheme: "https",
|
||||
handler: Box::new(HttpServiceBuilder::new(
|
||||
self.factory.clone(),
|
||||
acceptor,
|
||||
DefaultPipelineFactory::new(
|
||||
self.factory.clone(),
|
||||
@ -346,6 +343,7 @@ where
|
||||
addr,
|
||||
scheme: "https",
|
||||
handler: Box::new(HttpServiceBuilder::new(
|
||||
self.factory.clone(),
|
||||
acceptor.clone(),
|
||||
DefaultPipelineFactory::new(
|
||||
self.factory.clone(),
|
||||
@ -493,10 +491,10 @@ impl<H: IntoHttpHandler, F: Fn() -> H + Send + Clone> HttpServer<H, F> {
|
||||
/// sys.run(); // <- Run actix system, this method starts all async processes
|
||||
/// }
|
||||
/// ```
|
||||
pub fn start(mut self) -> Addr<Server> {
|
||||
pub fn start(mut self) -> Addr<server::Server> {
|
||||
ssl::max_concurrent_ssl_connect(self.maxconnrate);
|
||||
|
||||
let mut srv = Server::new()
|
||||
let mut srv = server::Server::new()
|
||||
.workers(self.threads)
|
||||
.maxconn(self.maxconn)
|
||||
.shutdown_timeout(self.shutdown_timeout);
|
||||
@ -605,143 +603,6 @@ impl<H: IntoHttpHandler, F: Fn() -> H + Send + Clone> HttpServer<H, F> {
|
||||
// }
|
||||
// }
|
||||
|
||||
struct HttpService<F, H, Io>
|
||||
where
|
||||
F: Fn() -> H,
|
||||
H: IntoHttpHandler,
|
||||
Io: IoStream,
|
||||
{
|
||||
factory: F,
|
||||
addr: net::SocketAddr,
|
||||
host: Option<String>,
|
||||
keep_alive: KeepAlive,
|
||||
_t: PhantomData<Io>,
|
||||
}
|
||||
|
||||
impl<F, H, Io> NewService for HttpService<F, H, Io>
|
||||
where
|
||||
F: Fn() -> H,
|
||||
H: IntoHttpHandler,
|
||||
Io: IoStream,
|
||||
{
|
||||
type Request = Io;
|
||||
type Response = ();
|
||||
type Error = ();
|
||||
type InitError = ();
|
||||
type Service = HttpServiceHandler<H::Handler, Io>;
|
||||
type Future = FutureResult<Self::Service, Self::Error>;
|
||||
|
||||
fn new_service(&self) -> Self::Future {
|
||||
let s = ServerSettings::new(Some(self.addr), &self.host, false);
|
||||
let app = (self.factory)().into_handler();
|
||||
|
||||
ok(HttpServiceHandler::new(app, self.keep_alive, s))
|
||||
}
|
||||
}
|
||||
|
||||
struct HttpServiceHandler<H, Io>
|
||||
where
|
||||
H: HttpHandler,
|
||||
Io: IoStream,
|
||||
{
|
||||
settings: WorkerSettings<H>,
|
||||
tcp_ka: Option<time::Duration>,
|
||||
_t: PhantomData<Io>,
|
||||
}
|
||||
|
||||
impl<H, Io> HttpServiceHandler<H, Io>
|
||||
where
|
||||
H: HttpHandler,
|
||||
Io: IoStream,
|
||||
{
|
||||
fn new(
|
||||
app: H, keep_alive: KeepAlive, settings: ServerSettings,
|
||||
) -> HttpServiceHandler<H, Io> {
|
||||
let tcp_ka = if let KeepAlive::Tcp(val) = keep_alive {
|
||||
Some(time::Duration::new(val as u64, 0))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let settings = WorkerSettings::new(app, keep_alive, settings);
|
||||
|
||||
HttpServiceHandler {
|
||||
tcp_ka,
|
||||
settings,
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, Io> Service for HttpServiceHandler<H, Io>
|
||||
where
|
||||
H: HttpHandler,
|
||||
Io: IoStream,
|
||||
{
|
||||
type Request = Io;
|
||||
type Response = ();
|
||||
type Error = ();
|
||||
type Future = HttpChannel<Io, H>;
|
||||
|
||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||
Ok(Async::Ready(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, mut req: Self::Request) -> Self::Future {
|
||||
let _ = req.set_nodelay(true);
|
||||
HttpChannel::new(self.settings.clone(), req, None)
|
||||
}
|
||||
|
||||
// fn shutdown(&self, force: bool) {
|
||||
// if force {
|
||||
// self.settings.head().traverse::<TcpStream, H>();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
trait ServiceFactory<H>
|
||||
where
|
||||
H: IntoHttpHandler,
|
||||
{
|
||||
fn register(&self, server: Server, lst: net::TcpListener) -> Server;
|
||||
}
|
||||
|
||||
struct SimpleFactory<H, F, P>
|
||||
where
|
||||
H: IntoHttpHandler,
|
||||
F: Fn() -> H + Send + Clone,
|
||||
P: HttpPipelineFactory<Io = TcpStream>,
|
||||
{
|
||||
pub addr: net::SocketAddr,
|
||||
pub factory: F,
|
||||
pub pipeline: P,
|
||||
}
|
||||
|
||||
impl<H: IntoHttpHandler, F, P> Clone for SimpleFactory<H, F, P>
|
||||
where
|
||||
P: HttpPipelineFactory<Io = TcpStream>,
|
||||
F: Fn() -> H + Send + Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
SimpleFactory {
|
||||
addr: self.addr,
|
||||
factory: self.factory.clone(),
|
||||
pipeline: self.pipeline.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, F, P> ServiceFactory<H> for SimpleFactory<H, F, P>
|
||||
where
|
||||
H: IntoHttpHandler + 'static,
|
||||
F: Fn() -> H + Send + Clone + 'static,
|
||||
P: HttpPipelineFactory<Io = TcpStream>,
|
||||
{
|
||||
fn register(&self, server: Server, lst: net::TcpListener) -> Server {
|
||||
let pipeline = self.pipeline.clone();
|
||||
server.listen(lst, move || pipeline.create())
|
||||
}
|
||||
}
|
||||
|
||||
fn create_tcp_listener(
|
||||
addr: net::SocketAddr, backlog: i32,
|
||||
) -> io::Result<net::TcpListener> {
|
||||
@ -753,183 +614,3 @@ fn create_tcp_listener(
|
||||
builder.bind(addr)?;
|
||||
Ok(builder.listen(backlog)?)
|
||||
}
|
||||
|
||||
pub struct HttpServiceBuilder<H, A, P> {
|
||||
acceptor: A,
|
||||
pipeline: P,
|
||||
t: PhantomData<H>,
|
||||
}
|
||||
|
||||
impl<H, A, P> HttpServiceBuilder<H, A, P>
|
||||
where
|
||||
A: AcceptorServiceFactory,
|
||||
P: HttpPipelineFactory<Io = A::Io>,
|
||||
H: IntoHttpHandler,
|
||||
{
|
||||
pub fn new(acceptor: A, pipeline: P) -> Self {
|
||||
Self {
|
||||
acceptor,
|
||||
pipeline,
|
||||
t: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn acceptor<A1>(self, acceptor: A1) -> HttpServiceBuilder<H, A1, P>
|
||||
where
|
||||
A1: AcceptorServiceFactory,
|
||||
{
|
||||
HttpServiceBuilder {
|
||||
acceptor,
|
||||
pipeline: self.pipeline,
|
||||
t: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pipeline<P1>(self, pipeline: P1) -> HttpServiceBuilder<H, A, P1>
|
||||
where
|
||||
P1: HttpPipelineFactory,
|
||||
{
|
||||
HttpServiceBuilder {
|
||||
pipeline,
|
||||
acceptor: self.acceptor,
|
||||
t: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn finish(&self) -> impl ServerServiceFactory {
|
||||
let acceptor = self.acceptor.clone();
|
||||
let pipeline = self.pipeline.clone();
|
||||
|
||||
move || acceptor.create().and_then(pipeline.create())
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, A, P> ServiceFactory<H> for HttpServiceBuilder<H, A, P>
|
||||
where
|
||||
A: AcceptorServiceFactory,
|
||||
P: HttpPipelineFactory<Io = A::Io>,
|
||||
H: IntoHttpHandler,
|
||||
{
|
||||
fn register(&self, server: Server, lst: net::TcpListener) -> Server {
|
||||
server.listen(lst, self.finish())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AcceptorServiceFactory: Send + Clone + 'static {
|
||||
type Io: IoStream + Send;
|
||||
type NewService: NewService<
|
||||
Request = TcpStream,
|
||||
Response = Self::Io,
|
||||
Error = (),
|
||||
InitError = (),
|
||||
>;
|
||||
|
||||
fn create(&self) -> Self::NewService;
|
||||
}
|
||||
|
||||
impl<F, T> AcceptorServiceFactory for F
|
||||
where
|
||||
F: Fn() -> T + Send + Clone + 'static,
|
||||
T::Response: IoStream + Send,
|
||||
T: NewService<Request = TcpStream, Error = (), InitError = ()>,
|
||||
{
|
||||
type Io = T::Response;
|
||||
type NewService = T;
|
||||
|
||||
fn create(&self) -> T {
|
||||
(self)()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HttpPipelineFactory: Send + Clone + 'static {
|
||||
type Io: IoStream;
|
||||
type NewService: NewService<
|
||||
Request = Self::Io,
|
||||
Response = (),
|
||||
Error = (),
|
||||
InitError = (),
|
||||
>;
|
||||
|
||||
fn create(&self) -> Self::NewService;
|
||||
}
|
||||
|
||||
impl<F, T> HttpPipelineFactory for F
|
||||
where
|
||||
F: Fn() -> T + Send + Clone + 'static,
|
||||
T: NewService<Response = (), Error = (), InitError = ()>,
|
||||
T::Request: IoStream,
|
||||
{
|
||||
type Io = T::Request;
|
||||
type NewService = T;
|
||||
|
||||
fn create(&self) -> T {
|
||||
(self)()
|
||||
}
|
||||
}
|
||||
|
||||
struct DefaultPipelineFactory<F, H, Io>
|
||||
where
|
||||
F: Fn() -> H + Send + Clone,
|
||||
{
|
||||
factory: F,
|
||||
host: Option<String>,
|
||||
addr: net::SocketAddr,
|
||||
keep_alive: KeepAlive,
|
||||
_t: PhantomData<Io>,
|
||||
}
|
||||
|
||||
impl<F, H, Io> DefaultPipelineFactory<F, H, Io>
|
||||
where
|
||||
Io: IoStream + Send,
|
||||
F: Fn() -> H + Send + Clone + 'static,
|
||||
H: IntoHttpHandler + 'static,
|
||||
{
|
||||
fn new(
|
||||
factory: F, host: Option<String>, addr: net::SocketAddr, keep_alive: KeepAlive,
|
||||
) -> Self {
|
||||
Self {
|
||||
factory,
|
||||
addr,
|
||||
keep_alive,
|
||||
host,
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, H, Io> Clone for DefaultPipelineFactory<F, H, Io>
|
||||
where
|
||||
Io: IoStream,
|
||||
F: Fn() -> H + Send + Clone,
|
||||
H: IntoHttpHandler,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
factory: self.factory.clone(),
|
||||
addr: self.addr,
|
||||
keep_alive: self.keep_alive,
|
||||
host: self.host.clone(),
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, H, Io> HttpPipelineFactory for DefaultPipelineFactory<F, H, Io>
|
||||
where
|
||||
Io: IoStream + Send,
|
||||
F: Fn() -> H + Send + Clone + 'static,
|
||||
H: IntoHttpHandler + 'static,
|
||||
{
|
||||
type Io = Io;
|
||||
type NewService = HttpService<F, H, Io>;
|
||||
|
||||
fn create(&self) -> Self::NewService {
|
||||
HttpService {
|
||||
addr: self.addr,
|
||||
keep_alive: self.keep_alive,
|
||||
host: self.host.clone(),
|
||||
factory: self.factory.clone(),
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -117,6 +117,7 @@ use tokio_tcp::TcpStream;
|
||||
|
||||
pub use actix_net::server::{PauseServer, ResumeServer, StopServer};
|
||||
|
||||
pub(crate) mod builder;
|
||||
mod channel;
|
||||
mod error;
|
||||
pub(crate) mod h1;
|
||||
@ -130,6 +131,7 @@ mod http;
|
||||
pub(crate) mod input;
|
||||
pub(crate) mod message;
|
||||
pub(crate) mod output;
|
||||
pub(crate) mod service;
|
||||
pub(crate) mod settings;
|
||||
mod ssl;
|
||||
|
||||
|
133
src/server/service.rs
Normal file
133
src/server/service.rs
Normal file
@ -0,0 +1,133 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::net;
|
||||
use std::time::Duration;
|
||||
|
||||
use actix_net::service::{NewService, Service};
|
||||
use futures::future::{ok, FutureResult};
|
||||
use futures::{Async, Poll};
|
||||
|
||||
use super::channel::HttpChannel;
|
||||
use super::handler::{HttpHandler, IntoHttpHandler};
|
||||
use super::settings::{ServerSettings, WorkerSettings};
|
||||
use super::{IoStream, KeepAlive};
|
||||
|
||||
pub enum HttpServiceMessage<T> {
|
||||
/// New stream
|
||||
Connect(T),
|
||||
/// Gracefull shutdown
|
||||
Shutdown(Duration),
|
||||
/// Force shutdown
|
||||
ForceShutdown,
|
||||
}
|
||||
|
||||
pub(crate) struct HttpService<F, H, Io>
|
||||
where
|
||||
F: Fn() -> H,
|
||||
H: IntoHttpHandler,
|
||||
Io: IoStream,
|
||||
{
|
||||
factory: F,
|
||||
addr: net::SocketAddr,
|
||||
host: Option<String>,
|
||||
keep_alive: KeepAlive,
|
||||
_t: PhantomData<Io>,
|
||||
}
|
||||
|
||||
impl<F, H, Io> HttpService<F, H, Io>
|
||||
where
|
||||
F: Fn() -> H,
|
||||
H: IntoHttpHandler,
|
||||
Io: IoStream,
|
||||
{
|
||||
pub fn new(
|
||||
factory: F, addr: net::SocketAddr, host: Option<String>, keep_alive: KeepAlive,
|
||||
) -> Self {
|
||||
HttpService {
|
||||
factory,
|
||||
addr,
|
||||
host,
|
||||
keep_alive,
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, H, Io> NewService for HttpService<F, H, Io>
|
||||
where
|
||||
F: Fn() -> H,
|
||||
H: IntoHttpHandler,
|
||||
Io: IoStream,
|
||||
{
|
||||
type Request = Io;
|
||||
type Response = ();
|
||||
type Error = ();
|
||||
type InitError = ();
|
||||
type Service = HttpServiceHandler<H::Handler, Io>;
|
||||
type Future = FutureResult<Self::Service, Self::Error>;
|
||||
|
||||
fn new_service(&self) -> Self::Future {
|
||||
let s = ServerSettings::new(Some(self.addr), &self.host, false);
|
||||
let app = (self.factory)().into_handler();
|
||||
|
||||
ok(HttpServiceHandler::new(app, self.keep_alive, s))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct HttpServiceHandler<H, Io>
|
||||
where
|
||||
H: HttpHandler,
|
||||
Io: IoStream,
|
||||
{
|
||||
settings: WorkerSettings<H>,
|
||||
tcp_ka: Option<Duration>,
|
||||
_t: PhantomData<Io>,
|
||||
}
|
||||
|
||||
impl<H, Io> HttpServiceHandler<H, Io>
|
||||
where
|
||||
H: HttpHandler,
|
||||
Io: IoStream,
|
||||
{
|
||||
fn new(
|
||||
app: H, keep_alive: KeepAlive, settings: ServerSettings,
|
||||
) -> HttpServiceHandler<H, Io> {
|
||||
let tcp_ka = if let KeepAlive::Tcp(val) = keep_alive {
|
||||
Some(Duration::new(val as u64, 0))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let settings = WorkerSettings::new(app, keep_alive, settings);
|
||||
|
||||
HttpServiceHandler {
|
||||
tcp_ka,
|
||||
settings,
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, Io> Service for HttpServiceHandler<H, Io>
|
||||
where
|
||||
H: HttpHandler,
|
||||
Io: IoStream,
|
||||
{
|
||||
type Request = Io;
|
||||
type Response = ();
|
||||
type Error = ();
|
||||
type Future = HttpChannel<Io, H>;
|
||||
|
||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||
Ok(Async::Ready(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, mut req: Self::Request) -> Self::Future {
|
||||
let _ = req.set_nodelay(true);
|
||||
HttpChannel::new(self.settings.clone(), req, None)
|
||||
}
|
||||
|
||||
// fn shutdown(&self, force: bool) {
|
||||
// if force {
|
||||
// self.settings.head().traverse::<TcpStream, H>();
|
||||
// }
|
||||
// }
|
||||
}
|
@ -2,7 +2,7 @@ use std::cell::{RefCell, RefMut, UnsafeCell};
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt::Write;
|
||||
use std::rc::Rc;
|
||||
use std::time::{Instant, Duration};
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{env, fmt, net};
|
||||
|
||||
use bytes::BytesMut;
|
||||
@ -12,8 +12,8 @@ use http::StatusCode;
|
||||
use lazycell::LazyCell;
|
||||
use parking_lot::Mutex;
|
||||
use time;
|
||||
use tokio_timer::{sleep, Delay};
|
||||
use tokio_current_thread::spawn;
|
||||
use tokio_timer::{sleep, Delay};
|
||||
|
||||
use super::channel::Node;
|
||||
use super::message::{Request, RequestPool};
|
||||
@ -183,9 +183,7 @@ impl<H> WorkerSettings<H> {
|
||||
pub fn keep_alive_timer(&self) -> Option<Delay> {
|
||||
let ka = self.0.keep_alive;
|
||||
if ka != 0 {
|
||||
Some(Delay::new(
|
||||
Instant::now() + Duration::from_secs(ka),
|
||||
))
|
||||
Some(Delay::new(Instant::now() + Duration::from_secs(ka)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -10,9 +10,9 @@ extern crate http as modhttp;
|
||||
extern crate rand;
|
||||
extern crate tokio;
|
||||
extern crate tokio_current_thread;
|
||||
extern crate tokio_current_thread as current_thread;
|
||||
extern crate tokio_reactor;
|
||||
extern crate tokio_tcp;
|
||||
extern crate tokio_current_thread as current_thread;
|
||||
|
||||
use std::io::{Read, Write};
|
||||
use std::sync::Arc;
|
||||
|
Loading…
Reference in New Issue
Block a user