mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-24 08:22:59 +01:00
separate mod for HttpHandler; add HttpHandler impl for Vec<H>
This commit is contained in:
parent
6f3e70a92a
commit
dbb4fab4f7
@ -447,7 +447,7 @@ where
|
|||||||
});
|
});
|
||||||
continue 'outer;
|
continue 'outer;
|
||||||
}
|
}
|
||||||
Err(msg) => {
|
Err(_) => {
|
||||||
// handler is not found
|
// handler is not found
|
||||||
self.tasks.push_back(Entry {
|
self.tasks.push_back(Entry {
|
||||||
pipe: EntryPipe::Error(ServerError::err(
|
pipe: EntryPipe::Error(ServerError::err(
|
||||||
@ -516,19 +516,22 @@ mod tests {
|
|||||||
use std::{cmp, io, time};
|
use std::{cmp, io, time};
|
||||||
|
|
||||||
use bytes::{Buf, Bytes, BytesMut};
|
use bytes::{Buf, Bytes, BytesMut};
|
||||||
|
use futures::future;
|
||||||
use http::{Method, Version};
|
use http::{Method, Version};
|
||||||
|
use tokio::runtime::current_thread;
|
||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use application::HttpApplication;
|
use application::{App, HttpApplication};
|
||||||
use httpmessage::HttpMessage;
|
use httpmessage::HttpMessage;
|
||||||
use server::h1decoder::Message;
|
use server::h1decoder::Message;
|
||||||
|
use server::handler::IntoHttpHandler;
|
||||||
use server::settings::{ServerSettings, WorkerSettings};
|
use server::settings::{ServerSettings, WorkerSettings};
|
||||||
use server::{KeepAlive, Request};
|
use server::{KeepAlive, Request};
|
||||||
|
|
||||||
fn wrk_settings() -> WorkerSettings<HttpApplication> {
|
fn wrk_settings() -> WorkerSettings<HttpApplication> {
|
||||||
WorkerSettings::<HttpApplication>::new(
|
WorkerSettings::<HttpApplication>::new(
|
||||||
Vec::new(),
|
App::new().into_handler(),
|
||||||
KeepAlive::Os,
|
KeepAlive::Os,
|
||||||
ServerSettings::default(),
|
ServerSettings::default(),
|
||||||
)
|
)
|
||||||
@ -646,30 +649,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_req_parse1() {
|
|
||||||
let buf = Buffer::new("GET /test HTTP/1.1\r\n\r\n");
|
|
||||||
let readbuf = BytesMut::new();
|
|
||||||
let settings = wrk_settings();
|
|
||||||
|
|
||||||
let mut h1 = Http1::new(settings.clone(), buf, None, readbuf, false, None);
|
|
||||||
h1.poll_io();
|
|
||||||
h1.poll_io();
|
|
||||||
assert_eq!(h1.tasks.len(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_req_parse2() {
|
|
||||||
let buf = Buffer::new("");
|
|
||||||
let readbuf =
|
|
||||||
BytesMut::from(Vec::<u8>::from(&b"GET /test HTTP/1.1\r\n\r\n"[..]));
|
|
||||||
let settings = wrk_settings();
|
|
||||||
|
|
||||||
let mut h1 = Http1::new(settings.clone(), buf, None, readbuf, true, None);
|
|
||||||
h1.poll_io();
|
|
||||||
assert_eq!(h1.tasks.len(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_req_parse_err() {
|
fn test_req_parse_err() {
|
||||||
let buf = Buffer::new("GET /test HTTP/1\r\n\r\n");
|
let buf = Buffer::new("GET /test HTTP/1\r\n\r\n");
|
||||||
|
@ -370,7 +370,7 @@ impl<H: HttpHandler + 'static> Entry<H> {
|
|||||||
// start request processing
|
// start request processing
|
||||||
let task = match settings.handler().handle(msg) {
|
let task = match settings.handler().handle(msg) {
|
||||||
Ok(task) => EntryPipe::Task(task),
|
Ok(task) => EntryPipe::Task(task),
|
||||||
Err(msg) => EntryPipe::Error(ServerError::err(
|
Err(_) => EntryPipe::Error(ServerError::err(
|
||||||
Version::HTTP_2,
|
Version::HTTP_2,
|
||||||
StatusCode::NOT_FOUND,
|
StatusCode::NOT_FOUND,
|
||||||
)),
|
)),
|
||||||
|
189
src/server/handler.rs
Normal file
189
src/server/handler.rs
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
use futures::{Async, Poll};
|
||||||
|
|
||||||
|
use super::message::Request;
|
||||||
|
use super::Writer;
|
||||||
|
use error::Error;
|
||||||
|
|
||||||
|
/// Low level http request handler
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
pub trait HttpHandler: 'static {
|
||||||
|
/// Request handling task
|
||||||
|
type Task: HttpHandlerTask;
|
||||||
|
|
||||||
|
/// Handle request
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Low level http request handler
|
||||||
|
pub trait HttpHandlerTask {
|
||||||
|
/// Poll task, this method is used before or after *io* object is available
|
||||||
|
fn poll_completed(&mut self) -> Poll<(), Error> {
|
||||||
|
Ok(Async::Ready(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Poll task when *io* object is available
|
||||||
|
fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error>;
|
||||||
|
|
||||||
|
/// Connection is disconnected
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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) -> Self::Handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: HttpHandler> IntoHttpHandler for T {
|
||||||
|
type Handler = T;
|
||||||
|
|
||||||
|
fn into_handler(self) -> Self::Handler {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: IntoHttpHandler> IntoHttpHandler for Vec<T> {
|
||||||
|
type Handler = VecHttpHandler<T::Handler>;
|
||||||
|
|
||||||
|
fn into_handler(self) -> Self::Handler {
|
||||||
|
VecHttpHandler(self.into_iter().map(|item| item.into_handler()).collect())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct VecHttpHandler<H: HttpHandler>(Vec<H>);
|
||||||
|
|
||||||
|
impl<H: HttpHandler> HttpHandler for VecHttpHandler<H> {
|
||||||
|
type Task = H::Task;
|
||||||
|
|
||||||
|
fn handle(&self, mut req: Request) -> Result<Self::Task, Request> {
|
||||||
|
for h in &self.0 {
|
||||||
|
req = match h.handle(req) {
|
||||||
|
Ok(task) => return Ok(task),
|
||||||
|
Err(e) => e,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Err(req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! http_handler ({$EN:ident, $(($n:tt, $T:ident)),+} => {
|
||||||
|
impl<$($T: HttpHandler,)+> HttpHandler for ($($T,)+) {
|
||||||
|
type Task = $EN<$($T,)+>;
|
||||||
|
|
||||||
|
fn handle(&self, mut req: Request) -> Result<Self::Task, Request> {
|
||||||
|
$(
|
||||||
|
req = match self.$n.handle(req) {
|
||||||
|
Ok(task) => return Ok($EN::$T(task)),
|
||||||
|
Err(e) => e,
|
||||||
|
};
|
||||||
|
)+
|
||||||
|
Err(req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub enum $EN<$($T: HttpHandler,)+> {
|
||||||
|
$($T ($T::Task),)+
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<$($T: HttpHandler,)+> HttpHandlerTask for $EN<$($T,)+>
|
||||||
|
{
|
||||||
|
fn poll_completed(&mut self) -> Poll<(), Error> {
|
||||||
|
match self {
|
||||||
|
$($EN :: $T(ref mut task) => task.poll_completed(),)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error> {
|
||||||
|
match self {
|
||||||
|
$($EN::$T(ref mut task) => task.poll_io(io),)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connection is disconnected
|
||||||
|
fn disconnected(&mut self) {
|
||||||
|
match self {
|
||||||
|
$($EN::$T(ref mut task) => task.disconnected(),)+
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
http_handler!(HttpHandlerTask1, (0, A));
|
||||||
|
http_handler!(HttpHandlerTask2, (0, A), (1, B));
|
||||||
|
http_handler!(HttpHandlerTask3, (0, A), (1, B), (2, C));
|
||||||
|
http_handler!(HttpHandlerTask4, (0, A), (1, B), (2, C), (3, D));
|
||||||
|
http_handler!(HttpHandlerTask5, (0, A), (1, B), (2, C), (3, D), (4, E));
|
||||||
|
http_handler!(
|
||||||
|
HttpHandlerTask6,
|
||||||
|
(0, A),
|
||||||
|
(1, B),
|
||||||
|
(2, C),
|
||||||
|
(3, D),
|
||||||
|
(4, E),
|
||||||
|
(5, F)
|
||||||
|
);
|
||||||
|
http_handler!(
|
||||||
|
HttpHandlerTask7,
|
||||||
|
(0, A),
|
||||||
|
(1, B),
|
||||||
|
(2, C),
|
||||||
|
(3, D),
|
||||||
|
(4, E),
|
||||||
|
(5, F),
|
||||||
|
(6, G)
|
||||||
|
);
|
||||||
|
http_handler!(
|
||||||
|
HttpHandlerTask8,
|
||||||
|
(0, A),
|
||||||
|
(1, B),
|
||||||
|
(2, C),
|
||||||
|
(3, D),
|
||||||
|
(4, E),
|
||||||
|
(5, F),
|
||||||
|
(6, G),
|
||||||
|
(7, H)
|
||||||
|
);
|
||||||
|
http_handler!(
|
||||||
|
HttpHandlerTask9,
|
||||||
|
(0, A),
|
||||||
|
(1, B),
|
||||||
|
(2, C),
|
||||||
|
(3, D),
|
||||||
|
(4, E),
|
||||||
|
(5, F),
|
||||||
|
(6, G),
|
||||||
|
(7, H),
|
||||||
|
(8, I)
|
||||||
|
);
|
||||||
|
http_handler!(
|
||||||
|
HttpHandlerTask10,
|
||||||
|
(0, A),
|
||||||
|
(1, B),
|
||||||
|
(2, C),
|
||||||
|
(3, D),
|
||||||
|
(4, E),
|
||||||
|
(5, F),
|
||||||
|
(6, G),
|
||||||
|
(7, H),
|
||||||
|
(8, I),
|
||||||
|
(9, J)
|
||||||
|
);
|
@ -3,7 +3,8 @@ use std::{io, mem, net, time};
|
|||||||
|
|
||||||
use actix::{Actor, Addr, AsyncContext, Context, Handler, System};
|
use actix::{Actor, Addr, AsyncContext, Context, Handler, System};
|
||||||
use actix_net::server::{Server, ServerServiceFactory};
|
use actix_net::server::{Server, ServerServiceFactory};
|
||||||
use actix_net::{ssl, NewService, NewServiceExt, Service};
|
use actix_net::service::{NewService, NewServiceExt, Service};
|
||||||
|
use actix_net::ssl;
|
||||||
|
|
||||||
use futures::future::{ok, FutureResult};
|
use futures::future::{ok, FutureResult};
|
||||||
use futures::{Async, Poll, Stream};
|
use futures::{Async, Poll, Stream};
|
||||||
|
@ -115,7 +115,7 @@ use futures::{Async, Poll};
|
|||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio_tcp::TcpStream;
|
use tokio_tcp::TcpStream;
|
||||||
|
|
||||||
pub use actix_net::{PauseServer, ResumeServer, StopServer};
|
pub use actix_net::server::{PauseServer, ResumeServer, StopServer};
|
||||||
|
|
||||||
mod channel;
|
mod channel;
|
||||||
mod error;
|
mod error;
|
||||||
@ -124,25 +124,25 @@ pub(crate) mod h1decoder;
|
|||||||
mod h1writer;
|
mod h1writer;
|
||||||
mod h2;
|
mod h2;
|
||||||
mod h2writer;
|
mod h2writer;
|
||||||
|
mod handler;
|
||||||
pub(crate) mod helpers;
|
pub(crate) mod helpers;
|
||||||
mod http;
|
mod http;
|
||||||
pub(crate) mod input;
|
pub(crate) mod input;
|
||||||
pub(crate) mod message;
|
pub(crate) mod message;
|
||||||
pub(crate) mod output;
|
pub(crate) mod output;
|
||||||
pub(crate) mod settings;
|
pub(crate) mod settings;
|
||||||
|
|
||||||
mod ssl;
|
mod ssl;
|
||||||
pub use self::ssl::*;
|
|
||||||
|
|
||||||
|
pub use self::handler::*;
|
||||||
pub use self::http::HttpServer;
|
pub use self::http::HttpServer;
|
||||||
pub use self::message::Request;
|
pub use self::message::Request;
|
||||||
pub use self::settings::ServerSettings;
|
pub use self::settings::ServerSettings;
|
||||||
|
pub use self::ssl::*;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use self::helpers::write_content_length;
|
pub use self::helpers::write_content_length;
|
||||||
|
|
||||||
use body::Binary;
|
use body::Binary;
|
||||||
use error::Error;
|
|
||||||
use extensions::Extensions;
|
use extensions::Extensions;
|
||||||
use header::ContentEncoding;
|
use header::ContentEncoding;
|
||||||
use httpresponse::HttpResponse;
|
use httpresponse::HttpResponse;
|
||||||
@ -222,61 +222,6 @@ impl From<Option<usize>> for KeepAlive {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Low level http request handler
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
pub trait HttpHandler: 'static {
|
|
||||||
/// Request handling task
|
|
||||||
type Task: HttpHandlerTask;
|
|
||||||
|
|
||||||
/// Handle request
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Low level http request handler
|
|
||||||
pub trait HttpHandlerTask {
|
|
||||||
/// Poll task, this method is used before or after *io* object is available
|
|
||||||
fn poll_completed(&mut self) -> Poll<(), Error> {
|
|
||||||
Ok(Async::Ready(()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Poll task when *io* object is available
|
|
||||||
fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error>;
|
|
||||||
|
|
||||||
/// Connection is disconnected
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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) -> Self::Handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: HttpHandler> IntoHttpHandler for T {
|
|
||||||
type Handler = T;
|
|
||||||
|
|
||||||
fn into_handler(self) -> Self::Handler {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum WriterState {
|
pub enum WriterState {
|
||||||
|
@ -316,11 +316,8 @@ mod tests {
|
|||||||
let mut rt = current_thread::Runtime::new().unwrap();
|
let mut rt = current_thread::Runtime::new().unwrap();
|
||||||
|
|
||||||
let _ = rt.block_on(future::lazy(|| {
|
let _ = rt.block_on(future::lazy(|| {
|
||||||
let settings = WorkerSettings::<()>::new(
|
let settings =
|
||||||
Vec::new(),
|
WorkerSettings::<()>::new((), KeepAlive::Os, ServerSettings::default());
|
||||||
KeepAlive::Os,
|
|
||||||
ServerSettings::default(),
|
|
||||||
);
|
|
||||||
let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
|
let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
|
||||||
settings.set_date(&mut buf1, true);
|
settings.set_date(&mut buf1, true);
|
||||||
let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
|
let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
|
||||||
|
Loading…
Reference in New Issue
Block a user