mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-24 07:53:00 +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;
|
||||
}
|
||||
Err(msg) => {
|
||||
Err(_) => {
|
||||
// handler is not found
|
||||
self.tasks.push_back(Entry {
|
||||
pipe: EntryPipe::Error(ServerError::err(
|
||||
@ -516,19 +516,22 @@ mod tests {
|
||||
use std::{cmp, io, time};
|
||||
|
||||
use bytes::{Buf, Bytes, BytesMut};
|
||||
use futures::future;
|
||||
use http::{Method, Version};
|
||||
use tokio::runtime::current_thread;
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
|
||||
use super::*;
|
||||
use application::HttpApplication;
|
||||
use application::{App, HttpApplication};
|
||||
use httpmessage::HttpMessage;
|
||||
use server::h1decoder::Message;
|
||||
use server::handler::IntoHttpHandler;
|
||||
use server::settings::{ServerSettings, WorkerSettings};
|
||||
use server::{KeepAlive, Request};
|
||||
|
||||
fn wrk_settings() -> WorkerSettings<HttpApplication> {
|
||||
WorkerSettings::<HttpApplication>::new(
|
||||
Vec::new(),
|
||||
App::new().into_handler(),
|
||||
KeepAlive::Os,
|
||||
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]
|
||||
fn test_req_parse_err() {
|
||||
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
|
||||
let task = match settings.handler().handle(msg) {
|
||||
Ok(task) => EntryPipe::Task(task),
|
||||
Err(msg) => EntryPipe::Error(ServerError::err(
|
||||
Err(_) => EntryPipe::Error(ServerError::err(
|
||||
Version::HTTP_2,
|
||||
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_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::{Async, Poll, Stream};
|
||||
|
@ -115,7 +115,7 @@ use futures::{Async, Poll};
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
use tokio_tcp::TcpStream;
|
||||
|
||||
pub use actix_net::{PauseServer, ResumeServer, StopServer};
|
||||
pub use actix_net::server::{PauseServer, ResumeServer, StopServer};
|
||||
|
||||
mod channel;
|
||||
mod error;
|
||||
@ -124,25 +124,25 @@ pub(crate) mod h1decoder;
|
||||
mod h1writer;
|
||||
mod h2;
|
||||
mod h2writer;
|
||||
mod handler;
|
||||
pub(crate) mod helpers;
|
||||
mod http;
|
||||
pub(crate) mod input;
|
||||
pub(crate) mod message;
|
||||
pub(crate) mod output;
|
||||
pub(crate) mod settings;
|
||||
|
||||
mod ssl;
|
||||
pub use self::ssl::*;
|
||||
|
||||
pub use self::handler::*;
|
||||
pub use self::http::HttpServer;
|
||||
pub use self::message::Request;
|
||||
pub use self::settings::ServerSettings;
|
||||
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;
|
||||
@ -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)]
|
||||
#[derive(Debug)]
|
||||
pub enum WriterState {
|
||||
|
@ -316,11 +316,8 @@ mod tests {
|
||||
let mut rt = current_thread::Runtime::new().unwrap();
|
||||
|
||||
let _ = rt.block_on(future::lazy(|| {
|
||||
let settings = WorkerSettings::<()>::new(
|
||||
Vec::new(),
|
||||
KeepAlive::Os,
|
||||
ServerSettings::default(),
|
||||
);
|
||||
let settings =
|
||||
WorkerSettings::<()>::new((), KeepAlive::Os, ServerSettings::default());
|
||||
let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
|
||||
settings.set_date(&mut buf1, true);
|
||||
let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
|
||||
|
Loading…
Reference in New Issue
Block a user