mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-28 01:32:57 +01:00
Merge branch 'master' into ws-trait
This commit is contained in:
commit
bb61dd41af
@ -12,6 +12,10 @@
|
||||
|
||||
* Allow to access Error's backtrace object
|
||||
|
||||
* Allow to override files listing renderer for `StaticFiles` #203
|
||||
|
||||
* Various extractor usability improvements #207
|
||||
|
||||
|
||||
## 0.5.6 (2018-04-24)
|
||||
|
||||
|
14
MIGRATION.md
14
MIGRATION.md
@ -15,6 +15,20 @@
|
||||
|
||||
* `FromRequest::Result` has to implement `Into<Reply<Self>>`
|
||||
|
||||
* `HttpRequest::query()` is deprecated. Use `Query` extractor.
|
||||
|
||||
```rust
|
||||
fn index(q: Query<HashMap<String, String>>) -> Result<..> {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```rust
|
||||
let q = Query::<HashMap<String, String>>::extract(req);
|
||||
```
|
||||
|
||||
|
||||
## Migration from 0.4 to 0.5
|
||||
|
||||
|
@ -805,8 +805,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_backtrace() {
|
||||
let orig = ErrorBadRequest("err");
|
||||
let e: Error = orig.into();
|
||||
let e = ErrorBadRequest("err");
|
||||
assert!(e.backtrace().is_some());
|
||||
}
|
||||
|
||||
|
188
src/extractor.rs
188
src/extractor.rs
@ -1,17 +1,18 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::str;
|
||||
|
||||
use bytes::Bytes;
|
||||
use encoding::all::UTF_8;
|
||||
use encoding::types::{DecoderTrap, Encoding};
|
||||
use futures::future::Future;
|
||||
use futures::{Async, Future, Poll};
|
||||
use mime::Mime;
|
||||
use serde::de::{self, DeserializeOwned};
|
||||
use serde_urlencoded;
|
||||
|
||||
use de::PathDeserializer;
|
||||
use error::{Error, ErrorBadRequest};
|
||||
use handler::FromRequest;
|
||||
use handler::{FromRequest, Reply};
|
||||
use httpmessage::{HttpMessage, MessageBody, UrlEncoded};
|
||||
use httprequest::HttpRequest;
|
||||
|
||||
@ -99,13 +100,12 @@ impl<T> Path<T> {
|
||||
impl<T, S> FromRequest<S> for Path<T>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
S: 'static,
|
||||
{
|
||||
type Config = ();
|
||||
type Result = Result<Self, Error>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
fn from_request(req: &HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
let req = req.clone();
|
||||
de::Deserialize::deserialize(PathDeserializer::new(&req))
|
||||
.map_err(|e| e.into())
|
||||
@ -167,13 +167,12 @@ impl<T> Query<T> {
|
||||
impl<T, S> FromRequest<S> for Query<T>
|
||||
where
|
||||
T: de::DeserializeOwned,
|
||||
S: 'static,
|
||||
{
|
||||
type Config = ();
|
||||
type Result = Result<Self, Error>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
fn from_request(req: &HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
let req = req.clone();
|
||||
serde_urlencoded::from_str::<T>(req.query_string())
|
||||
.map_err(|e| e.into())
|
||||
@ -241,7 +240,7 @@ where
|
||||
type Result = Box<Future<Item = Self, Error = Error>>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
Box::new(
|
||||
UrlEncoded::new(req.clone())
|
||||
.limit(cfg.limit)
|
||||
@ -326,7 +325,7 @@ impl<S: 'static> FromRequest<S> for Bytes {
|
||||
type Result = Result<Box<Future<Item = Self, Error = Error>>, Error>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
// check content-type
|
||||
cfg.check_mimetype(req)?;
|
||||
|
||||
@ -370,7 +369,7 @@ impl<S: 'static> FromRequest<S> for String {
|
||||
type Result = Result<Box<Future<Item = String, Error = Error>>, Error>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
// check content-type
|
||||
cfg.check_mimetype(req)?;
|
||||
|
||||
@ -447,6 +446,123 @@ impl Default for PayloadConfig {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! tuple_from_req ({$fut_type:ident, $(($n:tt, $T:ident)),+} => {
|
||||
|
||||
/// FromRequest implementation for tuple
|
||||
impl<S, $($T: FromRequest<S> + 'static),+> FromRequest<S> for ($($T,)+)
|
||||
where
|
||||
S: 'static,
|
||||
{
|
||||
type Config = ($($T::Config,)+);
|
||||
type Result = Box<Future<Item = ($($T,)+), Error = Error>>;
|
||||
|
||||
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
Box::new($fut_type {
|
||||
s: PhantomData,
|
||||
items: <($(Option<$T>,)+)>::default(),
|
||||
futs: ($(Some($T::from_request(req, &cfg.$n).into()),)+),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct $fut_type<S, $($T: FromRequest<S>),+>
|
||||
where
|
||||
S: 'static,
|
||||
{
|
||||
s: PhantomData<S>,
|
||||
items: ($(Option<$T>,)+),
|
||||
futs: ($(Option<Reply<$T>>,)+),
|
||||
}
|
||||
|
||||
impl<S, $($T: FromRequest<S>),+> Future for $fut_type<S, $($T),+>
|
||||
where
|
||||
S: 'static,
|
||||
{
|
||||
type Item = ($($T,)+);
|
||||
type Error = Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
let mut ready = true;
|
||||
|
||||
$(
|
||||
if self.futs.$n.is_some() {
|
||||
match self.futs.$n.as_mut().unwrap().poll() {
|
||||
Ok(Async::Ready(item)) => {
|
||||
self.items.$n = Some(item);
|
||||
self.futs.$n.take();
|
||||
}
|
||||
Ok(Async::NotReady) => ready = false,
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
)+
|
||||
|
||||
if ready {
|
||||
Ok(Async::Ready(
|
||||
($(self.items.$n.take().unwrap(),)+)
|
||||
))
|
||||
} else {
|
||||
Ok(Async::NotReady)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
tuple_from_req!(TupleFromRequest1, (0, A));
|
||||
tuple_from_req!(TupleFromRequest2, (0, A), (1, B));
|
||||
tuple_from_req!(TupleFromRequest3, (0, A), (1, B), (2, C));
|
||||
tuple_from_req!(TupleFromRequest4, (0, A), (1, B), (2, C), (3, D));
|
||||
tuple_from_req!(
|
||||
TupleFromRequest5,
|
||||
(0, A),
|
||||
(1, B),
|
||||
(2, C),
|
||||
(3, D),
|
||||
(4, E)
|
||||
);
|
||||
tuple_from_req!(
|
||||
TupleFromRequest6,
|
||||
(0, A),
|
||||
(1, B),
|
||||
(2, C),
|
||||
(3, D),
|
||||
(4, E),
|
||||
(5, F)
|
||||
);
|
||||
tuple_from_req!(
|
||||
TupleFromRequest7,
|
||||
(0, A),
|
||||
(1, B),
|
||||
(2, C),
|
||||
(3, D),
|
||||
(4, E),
|
||||
(5, F),
|
||||
(6, G)
|
||||
);
|
||||
tuple_from_req!(
|
||||
TupleFromRequest8,
|
||||
(0, A),
|
||||
(1, B),
|
||||
(2, C),
|
||||
(3, D),
|
||||
(4, E),
|
||||
(5, F),
|
||||
(6, G),
|
||||
(7, H)
|
||||
);
|
||||
tuple_from_req!(
|
||||
TupleFromRequest9,
|
||||
(0, A),
|
||||
(1, B),
|
||||
(2, C),
|
||||
(3, D),
|
||||
(4, E),
|
||||
(5, F),
|
||||
(6, G),
|
||||
(7, H),
|
||||
(8, I)
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -471,7 +587,7 @@ mod tests {
|
||||
req.payload_mut()
|
||||
.unread_data(Bytes::from_static(b"hello=world"));
|
||||
|
||||
match Bytes::from_request(&mut req, &cfg)
|
||||
match Bytes::from_request(&req, &cfg)
|
||||
.unwrap()
|
||||
.poll()
|
||||
.unwrap()
|
||||
@ -490,7 +606,7 @@ mod tests {
|
||||
req.payload_mut()
|
||||
.unread_data(Bytes::from_static(b"hello=world"));
|
||||
|
||||
match String::from_request(&mut req, &cfg)
|
||||
match String::from_request(&req, &cfg)
|
||||
.unwrap()
|
||||
.poll()
|
||||
.unwrap()
|
||||
@ -514,10 +630,7 @@ mod tests {
|
||||
|
||||
let mut cfg = FormConfig::default();
|
||||
cfg.limit(4096);
|
||||
match Form::<Info>::from_request(&mut req, &cfg)
|
||||
.poll()
|
||||
.unwrap()
|
||||
{
|
||||
match Form::<Info>::from_request(&req, &cfg).poll().unwrap() {
|
||||
Async::Ready(s) => {
|
||||
assert_eq!(s.hello, "world");
|
||||
}
|
||||
@ -574,29 +687,29 @@ mod tests {
|
||||
let (router, _) = Router::new("", ServerSettings::default(), routes);
|
||||
assert!(router.recognize(&mut req).is_some());
|
||||
|
||||
let s = Path::<MyStruct>::from_request(&mut req, &()).unwrap();
|
||||
let s = Path::<MyStruct>::from_request(&req, &()).unwrap();
|
||||
assert_eq!(s.key, "name");
|
||||
assert_eq!(s.value, "user1");
|
||||
|
||||
let s = Path::<(String, String)>::from_request(&mut req, &()).unwrap();
|
||||
let s = Path::<(String, String)>::from_request(&req, &()).unwrap();
|
||||
assert_eq!(s.0, "name");
|
||||
assert_eq!(s.1, "user1");
|
||||
|
||||
let s = Query::<Id>::from_request(&mut req, &()).unwrap();
|
||||
let s = Query::<Id>::from_request(&req, &()).unwrap();
|
||||
assert_eq!(s.id, "test");
|
||||
|
||||
let mut req = TestRequest::with_uri("/name/32/").finish();
|
||||
assert!(router.recognize(&mut req).is_some());
|
||||
|
||||
let s = Path::<Test2>::from_request(&mut req, &()).unwrap();
|
||||
let s = Path::<Test2>::from_request(&req, &()).unwrap();
|
||||
assert_eq!(s.as_ref().key, "name");
|
||||
assert_eq!(s.value, 32);
|
||||
|
||||
let s = Path::<(String, u8)>::from_request(&mut req, &()).unwrap();
|
||||
let s = Path::<(String, u8)>::from_request(&req, &()).unwrap();
|
||||
assert_eq!(s.0, "name");
|
||||
assert_eq!(s.1, 32);
|
||||
|
||||
let res = Path::<Vec<String>>::from_request(&mut req, &()).unwrap();
|
||||
let res = Path::<Vec<String>>::extract(&req).unwrap();
|
||||
assert_eq!(res[0], "name".to_owned());
|
||||
assert_eq!(res[1], "32".to_owned());
|
||||
}
|
||||
@ -614,4 +727,37 @@ mod tests {
|
||||
|
||||
assert_eq!(*Path::<i8>::from_request(&mut req, &()).unwrap(), 32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tuple_extract() {
|
||||
let mut req = TestRequest::with_uri("/name/user1/?id=test").finish();
|
||||
|
||||
let mut resource = ResourceHandler::<()>::default();
|
||||
resource.name("index");
|
||||
let mut routes = Vec::new();
|
||||
routes.push((
|
||||
Resource::new("index", "/{key}/{value}/"),
|
||||
Some(resource),
|
||||
));
|
||||
let (router, _) = Router::new("", ServerSettings::default(), routes);
|
||||
assert!(router.recognize(&mut req).is_some());
|
||||
|
||||
let res = match <(Path<(String, String)>,)>::extract(&req).poll() {
|
||||
Ok(Async::Ready(res)) => res,
|
||||
_ => panic!("error"),
|
||||
};
|
||||
assert_eq!((res.0).0, "name");
|
||||
assert_eq!((res.0).1, "user1");
|
||||
|
||||
let res = match <(Path<(String, String)>, Path<(String, String)>)>::extract(&req)
|
||||
.poll()
|
||||
{
|
||||
Ok(Async::Ready(res)) => res,
|
||||
_ => panic!("error"),
|
||||
};
|
||||
assert_eq!((res.0).0, "name");
|
||||
assert_eq!((res.0).1, "user1");
|
||||
assert_eq!((res.1).0, "name");
|
||||
assert_eq!((res.1).1, "user1");
|
||||
}
|
||||
}
|
||||
|
120
src/fs.rs
120
src/fs.rs
@ -365,11 +365,14 @@ impl Stream for ChunkedReadFile {
|
||||
}
|
||||
}
|
||||
|
||||
type DirectoryRenderer<S> =
|
||||
Fn(&Directory, &HttpRequest<S>) -> Result<HttpResponse, io::Error>;
|
||||
|
||||
/// A directory; responds with the generated directory listing.
|
||||
#[derive(Debug)]
|
||||
pub struct Directory {
|
||||
base: PathBuf,
|
||||
path: PathBuf,
|
||||
pub base: PathBuf,
|
||||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
impl Directory {
|
||||
@ -377,7 +380,7 @@ impl Directory {
|
||||
Directory { base, path }
|
||||
}
|
||||
|
||||
fn can_list(&self, entry: &io::Result<DirEntry>) -> bool {
|
||||
pub fn is_visible(&self, entry: &io::Result<DirEntry>) -> bool {
|
||||
if let Ok(ref entry) = *entry {
|
||||
if let Some(name) = entry.file_name().to_str() {
|
||||
if name.starts_with('.') {
|
||||
@ -393,61 +396,58 @@ impl Directory {
|
||||
}
|
||||
}
|
||||
|
||||
impl Responder for Directory {
|
||||
type Item = HttpResponse;
|
||||
type Error = io::Error;
|
||||
fn directory_listing<S>(
|
||||
dir: &Directory, req: &HttpRequest<S>,
|
||||
) -> Result<HttpResponse, io::Error> {
|
||||
let index_of = format!("Index of {}", req.path());
|
||||
let mut body = String::new();
|
||||
let base = Path::new(req.path());
|
||||
|
||||
fn respond_to(self, req: HttpRequest) -> Result<HttpResponse, io::Error> {
|
||||
let index_of = format!("Index of {}", req.path());
|
||||
let mut body = String::new();
|
||||
let base = Path::new(req.path());
|
||||
for entry in dir.path.read_dir()? {
|
||||
if dir.is_visible(&entry) {
|
||||
let entry = entry.unwrap();
|
||||
let p = match entry.path().strip_prefix(&dir.path) {
|
||||
Ok(p) => base.join(p),
|
||||
Err(_) => continue,
|
||||
};
|
||||
// show file url as relative to static path
|
||||
let file_url = format!("{}", p.to_string_lossy());
|
||||
|
||||
for entry in self.path.read_dir()? {
|
||||
if self.can_list(&entry) {
|
||||
let entry = entry.unwrap();
|
||||
let p = match entry.path().strip_prefix(&self.path) {
|
||||
Ok(p) => base.join(p),
|
||||
Err(_) => continue,
|
||||
};
|
||||
// show file url as relative to static path
|
||||
let file_url = format!("{}", p.to_string_lossy());
|
||||
|
||||
// if file is a directory, add '/' to the end of the name
|
||||
if let Ok(metadata) = entry.metadata() {
|
||||
if metadata.is_dir() {
|
||||
let _ = write!(
|
||||
body,
|
||||
"<li><a href=\"{}\">{}/</a></li>",
|
||||
file_url,
|
||||
entry.file_name().to_string_lossy()
|
||||
);
|
||||
} else {
|
||||
let _ = write!(
|
||||
body,
|
||||
"<li><a href=\"{}\">{}</a></li>",
|
||||
file_url,
|
||||
entry.file_name().to_string_lossy()
|
||||
);
|
||||
}
|
||||
// if file is a directory, add '/' to the end of the name
|
||||
if let Ok(metadata) = entry.metadata() {
|
||||
if metadata.is_dir() {
|
||||
let _ = write!(
|
||||
body,
|
||||
"<li><a href=\"{}\">{}/</a></li>",
|
||||
file_url,
|
||||
entry.file_name().to_string_lossy()
|
||||
);
|
||||
} else {
|
||||
continue;
|
||||
let _ = write!(
|
||||
body,
|
||||
"<li><a href=\"{}\">{}</a></li>",
|
||||
file_url,
|
||||
entry.file_name().to_string_lossy()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let html = format!(
|
||||
"<html>\
|
||||
<head><title>{}</title></head>\
|
||||
<body><h1>{}</h1>\
|
||||
<ul>\
|
||||
{}\
|
||||
</ul></body>\n</html>",
|
||||
index_of, index_of, body
|
||||
);
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("text/html; charset=utf-8")
|
||||
.body(html))
|
||||
}
|
||||
|
||||
let html = format!(
|
||||
"<html>\
|
||||
<head><title>{}</title></head>\
|
||||
<body><h1>{}</h1>\
|
||||
<ul>\
|
||||
{}\
|
||||
</ul></body>\n</html>",
|
||||
index_of, index_of, body
|
||||
);
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("text/html; charset=utf-8")
|
||||
.body(html))
|
||||
}
|
||||
|
||||
/// Static files handling
|
||||
@ -472,6 +472,7 @@ pub struct StaticFiles<S> {
|
||||
show_index: bool,
|
||||
cpu_pool: CpuPool,
|
||||
default: Box<RouteHandler<S>>,
|
||||
renderer: Box<DirectoryRenderer<S>>,
|
||||
_chunk_size: usize,
|
||||
_follow_symlinks: bool,
|
||||
}
|
||||
@ -535,6 +536,7 @@ impl<S: 'static> StaticFiles<S> {
|
||||
default: Box::new(WrapHandler::new(|_| {
|
||||
HttpResponse::new(StatusCode::NOT_FOUND)
|
||||
})),
|
||||
renderer: Box::new(directory_listing),
|
||||
_chunk_size: 0,
|
||||
_follow_symlinks: false,
|
||||
}
|
||||
@ -548,6 +550,17 @@ impl<S: 'static> StaticFiles<S> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Set custom directory renderer
|
||||
pub fn files_listing_renderer<F>(mut self, f: F) -> Self
|
||||
where
|
||||
for<'r, 's> F: Fn(&'r Directory, &'s HttpRequest<S>)
|
||||
-> Result<HttpResponse, io::Error>
|
||||
+ 'static,
|
||||
{
|
||||
self.renderer = Box::new(f);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set index file
|
||||
///
|
||||
/// Redirects to specific index file for directory "/" instead of
|
||||
@ -601,9 +614,8 @@ impl<S: 'static> Handler<S> for StaticFiles<S> {
|
||||
.finish()
|
||||
.respond_to(req.drop_state())
|
||||
} else if self.show_index {
|
||||
Directory::new(self.directory.clone(), path)
|
||||
.respond_to(req.drop_state())?
|
||||
.respond_to(req.drop_state())
|
||||
let dir = Directory::new(self.directory.clone(), path);
|
||||
Ok((*self.renderer)(&dir, &req)?.into())
|
||||
} else {
|
||||
Ok(self.default.handle(req))
|
||||
}
|
||||
|
110
src/handler.rs
110
src/handler.rs
@ -1,5 +1,4 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
|
||||
use futures::future::{err, ok, Future};
|
||||
@ -36,10 +35,7 @@ pub trait Responder {
|
||||
/// Trait implemented by types that can be extracted from request.
|
||||
///
|
||||
/// Types that implement this trait can be used with `Route::with()` method.
|
||||
pub trait FromRequest<S>: Sized
|
||||
where
|
||||
S: 'static,
|
||||
{
|
||||
pub trait FromRequest<S>: Sized {
|
||||
/// Configuration for conversion process
|
||||
type Config: Default;
|
||||
|
||||
@ -47,7 +43,14 @@ where
|
||||
type Result: Into<Reply<Self>>;
|
||||
|
||||
/// Convert request to a Self
|
||||
fn from_request(req: &mut HttpRequest<S>, cfg: &Self::Config) -> Self::Result;
|
||||
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result;
|
||||
|
||||
/// Convert request to a Self
|
||||
///
|
||||
/// This method uses default extractor configuration
|
||||
fn extract(req: &HttpRequest<S>) -> Self::Result {
|
||||
Self::from_request(req, &Self::Config::default())
|
||||
}
|
||||
}
|
||||
|
||||
/// Combines two different responder types into a single type
|
||||
@ -185,77 +188,74 @@ where
|
||||
/// * Message(T) - ready item
|
||||
/// * Error(Error) - error happen during reply process
|
||||
/// * Future<T, Error> - reply process completes in the future
|
||||
pub struct Reply<T>(ReplyItem<T>);
|
||||
pub struct Reply<I, E = Error>(Option<ReplyResult<I, E>>);
|
||||
|
||||
impl<T> Future for Reply<T> {
|
||||
type Item = T;
|
||||
type Error = Error;
|
||||
impl<I, E> Future for Reply<I, E> {
|
||||
type Item = I;
|
||||
type Error = E;
|
||||
|
||||
fn poll(&mut self) -> Poll<T, Error> {
|
||||
let item = mem::replace(&mut self.0, ReplyItem::None);
|
||||
|
||||
match item {
|
||||
ReplyItem::Error(err) => Err(err),
|
||||
ReplyItem::Message(msg) => Ok(Async::Ready(msg)),
|
||||
ReplyItem::Future(mut fut) => match fut.poll() {
|
||||
fn poll(&mut self) -> Poll<I, E> {
|
||||
let res = self.0.take().expect("use after resolve");
|
||||
match res {
|
||||
ReplyResult::Ok(msg) => Ok(Async::Ready(msg)),
|
||||
ReplyResult::Err(err) => Err(err),
|
||||
ReplyResult::Future(mut fut) => match fut.poll() {
|
||||
Ok(Async::NotReady) => {
|
||||
self.0 = ReplyItem::Future(fut);
|
||||
self.0 = Some(ReplyResult::Future(fut));
|
||||
Ok(Async::NotReady)
|
||||
}
|
||||
Ok(Async::Ready(msg)) => Ok(Async::Ready(msg)),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum ReplyItem<T> {
|
||||
None,
|
||||
Error(Error),
|
||||
Message(T),
|
||||
Future(Box<Future<Item = T, Error = Error>>),
|
||||
pub(crate) enum ReplyResult<I, E> {
|
||||
Ok(I),
|
||||
Err(E),
|
||||
Future(Box<Future<Item = I, Error = E>>),
|
||||
}
|
||||
|
||||
impl<T> Reply<T> {
|
||||
impl<I, E> Reply<I, E> {
|
||||
/// Create async response
|
||||
#[inline]
|
||||
pub fn async<F>(fut: F) -> Reply<T>
|
||||
pub fn async<F>(fut: F) -> Reply<I, E>
|
||||
where
|
||||
F: Future<Item = T, Error = Error> + 'static,
|
||||
F: Future<Item = I, Error = E> + 'static,
|
||||
{
|
||||
Reply(ReplyItem::Future(Box::new(fut)))
|
||||
Reply(Some(ReplyResult::Future(Box::new(fut))))
|
||||
}
|
||||
|
||||
/// Send response
|
||||
#[inline]
|
||||
pub fn response<R: Into<T>>(response: R) -> Reply<T> {
|
||||
Reply(ReplyItem::Message(response.into()))
|
||||
pub fn response<R: Into<I>>(response: R) -> Reply<I, E> {
|
||||
Reply(Some(ReplyResult::Ok(response.into())))
|
||||
}
|
||||
|
||||
/// Send error
|
||||
#[inline]
|
||||
pub fn error<R: Into<Error>>(err: R) -> Reply<T> {
|
||||
Reply(ReplyItem::Error(err.into()))
|
||||
pub fn error<R: Into<E>>(err: R) -> Reply<I, E> {
|
||||
Reply(Some(ReplyResult::Err(err.into())))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn into(self) -> ReplyItem<T> {
|
||||
self.0
|
||||
pub(crate) fn into(self) -> ReplyResult<I, E> {
|
||||
self.0.expect("use after resolve")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn as_msg(&self) -> &T {
|
||||
match self.0 {
|
||||
ReplyItem::Message(ref resp) => resp,
|
||||
pub(crate) fn as_msg(&self) -> &I {
|
||||
match self.0.as_ref().unwrap() {
|
||||
&ReplyResult::Ok(ref resp) => resp,
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn as_err(&self) -> Option<&Error> {
|
||||
match self.0 {
|
||||
ReplyItem::Error(ref err) => Some(err),
|
||||
pub(crate) fn as_err(&self) -> Option<&E> {
|
||||
match self.0.as_ref().unwrap() {
|
||||
&ReplyResult::Err(ref err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -276,14 +276,14 @@ impl Responder for HttpResponse {
|
||||
|
||||
#[inline]
|
||||
fn respond_to(self, _: HttpRequest) -> Result<Reply<HttpResponse>, Error> {
|
||||
Ok(Reply(ReplyItem::Message(self)))
|
||||
Ok(Reply(Some(ReplyResult::Ok(self))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for Reply<T> {
|
||||
#[inline]
|
||||
fn from(resp: T) -> Reply<T> {
|
||||
Reply(ReplyItem::Message(resp))
|
||||
Reply(Some(ReplyResult::Ok(resp)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,7 +307,7 @@ impl<T, E: Into<Error>> From<Result<Reply<T>, E>> for Reply<T> {
|
||||
fn from(res: Result<Reply<T>, E>) -> Self {
|
||||
match res {
|
||||
Ok(val) => val,
|
||||
Err(err) => Reply(ReplyItem::Error(err.into())),
|
||||
Err(err) => Reply(Some(ReplyResult::Err(err.into()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -316,8 +316,8 @@ impl<T, E: Into<Error>> From<Result<T, E>> for Reply<T> {
|
||||
#[inline]
|
||||
fn from(res: Result<T, E>) -> Self {
|
||||
match res {
|
||||
Ok(val) => Reply(ReplyItem::Message(val)),
|
||||
Err(err) => Reply(ReplyItem::Error(err.into())),
|
||||
Ok(val) => Reply(Some(ReplyResult::Ok(val))),
|
||||
Err(err) => Reply(Some(ReplyResult::Err(err.into()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -328,8 +328,8 @@ impl<T, E: Into<Error>> From<Result<Box<Future<Item = T, Error = Error>>, E>>
|
||||
#[inline]
|
||||
fn from(res: Result<Box<Future<Item = T, Error = Error>>, E>) -> Self {
|
||||
match res {
|
||||
Ok(fut) => Reply(ReplyItem::Future(fut)),
|
||||
Err(err) => Reply(ReplyItem::Error(err.into())),
|
||||
Ok(fut) => Reply(Some(ReplyResult::Future(fut))),
|
||||
Err(err) => Reply(Some(ReplyResult::Err(err.into()))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -337,7 +337,7 @@ impl<T, E: Into<Error>> From<Result<Box<Future<Item = T, Error = Error>>, E>>
|
||||
impl<T> From<Box<Future<Item = T, Error = Error>>> for Reply<T> {
|
||||
#[inline]
|
||||
fn from(fut: Box<Future<Item = T, Error = Error>>) -> Reply<T> {
|
||||
Reply(ReplyItem::Future(fut))
|
||||
Reply(Some(ReplyResult::Future(fut)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,8 +356,8 @@ where
|
||||
fn respond_to(self, req: HttpRequest) -> Result<Reply<HttpResponse>, Error> {
|
||||
let fut = self.map_err(|e| e.into())
|
||||
.then(move |r| match r.respond_to(req) {
|
||||
Ok(reply) => match reply.into().0 {
|
||||
ReplyItem::Message(resp) => ok(resp),
|
||||
Ok(reply) => match reply.into().into() {
|
||||
ReplyResult::Ok(resp) => ok(resp),
|
||||
_ => panic!("Nested async replies are not supported"),
|
||||
},
|
||||
Err(e) => err(e),
|
||||
@ -452,8 +452,8 @@ where
|
||||
let req2 = req.drop_state();
|
||||
let fut = (self.h)(req).map_err(|e| e.into()).then(move |r| {
|
||||
match r.respond_to(req2) {
|
||||
Ok(reply) => match reply.into().0 {
|
||||
ReplyItem::Message(resp) => ok(resp),
|
||||
Ok(reply) => match reply.into().into() {
|
||||
ReplyResult::Ok(resp) => ok(resp),
|
||||
_ => panic!("Nested async replies are not supported"),
|
||||
},
|
||||
Err(e) => err(e),
|
||||
@ -505,12 +505,12 @@ impl<S> Deref for State<S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: 'static> FromRequest<S> for State<S> {
|
||||
impl<S> FromRequest<S> for State<S> {
|
||||
type Config = ();
|
||||
type Result = State<S>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
State(req.clone()).into()
|
||||
fn from_request(req: &HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
State(req.clone())
|
||||
}
|
||||
}
|
||||
|
@ -500,12 +500,12 @@ impl<S> Clone for HttpRequest<S> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: 'static> FromRequest<S> for HttpRequest<S> {
|
||||
impl<S> FromRequest<S> for HttpRequest<S> {
|
||||
type Config = ();
|
||||
type Result = Self;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
fn from_request(req: &HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
req.clone()
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ where
|
||||
type Result = Box<Future<Item = Self, Error = Error>>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &mut HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
let req = req.clone();
|
||||
let err = Rc::clone(&cfg.ehandler);
|
||||
Box::new(
|
||||
|
@ -21,7 +21,7 @@ pub use self::logger::Logger;
|
||||
|
||||
/// Middleware start result
|
||||
pub enum Started {
|
||||
/// Execution completed
|
||||
/// Middleware is completed, continue to next middleware
|
||||
Done,
|
||||
/// New http response got generated. If middleware generates response
|
||||
/// handler execution halts.
|
||||
|
@ -37,7 +37,7 @@
|
||||
//! use actix_web::{server, App, HttpRequest, Result};
|
||||
//! use actix_web::middleware::session::{RequestSession, SessionStorage, CookieSessionBackend};
|
||||
//!
|
||||
//! fn index(mut req: HttpRequest) -> Result<&'static str> {
|
||||
//! fn index(req: HttpRequest) -> Result<&'static str> {
|
||||
//! // access session data
|
||||
//! if let Some(count) = req.session().get::<i32>("counter")? {
|
||||
//! println!("SESSION value: {}", count);
|
||||
@ -525,3 +525,30 @@ impl<S> SessionBackend<S> for CookieSessionBackend {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use application::App;
|
||||
use test;
|
||||
|
||||
#[test]
|
||||
fn cookie_session() {
|
||||
let mut srv = test::TestServer::with_factory(|| {
|
||||
App::new()
|
||||
.middleware(SessionStorage::new(
|
||||
CookieSessionBackend::signed(&[0; 32]).secure(false),
|
||||
))
|
||||
.resource("/", |r| {
|
||||
r.f(|req| {
|
||||
let _ = req.session().set("counter", 100);
|
||||
"test"
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
let request = srv.get().uri(srv.url("/")).finish().unwrap();
|
||||
let response = srv.execute(request.send()).unwrap();
|
||||
assert!(response.cookie("actix-session").is_some());
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use application::Inner;
|
||||
use body::{Body, BodyStream};
|
||||
use context::{ActorHttpContext, Frame};
|
||||
use error::Error;
|
||||
use handler::{Reply, ReplyItem};
|
||||
use handler::{Reply, ReplyResult};
|
||||
use header::ContentEncoding;
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
@ -324,14 +324,13 @@ impl<S: 'static, H> WaitingResponse<S, H> {
|
||||
info: &mut PipelineInfo<S>, reply: Reply<HttpResponse>,
|
||||
) -> PipelineState<S, H> {
|
||||
match reply.into() {
|
||||
ReplyItem::Error(err) => RunMiddlewares::init(info, err.into()),
|
||||
ReplyItem::Message(resp) => RunMiddlewares::init(info, resp),
|
||||
ReplyItem::Future(fut) => PipelineState::Handler(WaitingResponse {
|
||||
ReplyResult::Err(err) => RunMiddlewares::init(info, err.into()),
|
||||
ReplyResult::Ok(resp) => RunMiddlewares::init(info, resp),
|
||||
ReplyResult::Future(fut) => PipelineState::Handler(WaitingResponse {
|
||||
fut,
|
||||
_s: PhantomData,
|
||||
_h: PhantomData,
|
||||
}),
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ use std::rc::Rc;
|
||||
use futures::{Async, Future, Poll};
|
||||
|
||||
use error::Error;
|
||||
use handler::{AsyncHandler, FromRequest, Handler, Reply, ReplyItem, Responder,
|
||||
use handler::{AsyncHandler, FromRequest, Handler, Reply, ReplyResult, Responder,
|
||||
RouteHandler, WrapHandler};
|
||||
use http::StatusCode;
|
||||
use httprequest::HttpRequest;
|
||||
@ -417,13 +417,12 @@ impl<S: 'static> WaitingResponse<S> {
|
||||
#[inline]
|
||||
fn init(info: &mut ComposeInfo<S>, reply: Reply<HttpResponse>) -> ComposeState<S> {
|
||||
match reply.into() {
|
||||
ReplyItem::Error(err) => RunMiddlewares::init(info, err.into()),
|
||||
ReplyItem::Message(resp) => RunMiddlewares::init(info, resp),
|
||||
ReplyItem::Future(fut) => ComposeState::Handler(WaitingResponse {
|
||||
ReplyResult::Err(err) => RunMiddlewares::init(info, err.into()),
|
||||
ReplyResult::Ok(resp) => RunMiddlewares::init(info, resp),
|
||||
ReplyResult::Future(fut) => ComposeState::Handler(WaitingResponse {
|
||||
fut,
|
||||
_s: PhantomData,
|
||||
}),
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ use std::rc::Rc;
|
||||
use futures::{Async, Future, Poll};
|
||||
|
||||
use error::Error;
|
||||
use handler::{FromRequest, Reply, ReplyItem, Responder, RouteHandler};
|
||||
use handler::{FromRequest, Reply, ReplyResult, Responder, RouteHandler};
|
||||
use http::Method;
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
@ -523,13 +523,12 @@ impl<S: 'static> WaitingResponse<S> {
|
||||
#[inline]
|
||||
fn init(info: &mut ComposeInfo<S>, reply: Reply<HttpResponse>) -> ComposeState<S> {
|
||||
match reply.into() {
|
||||
ReplyItem::Message(resp) => RunMiddlewares::init(info, resp),
|
||||
ReplyItem::Error(err) => RunMiddlewares::init(info, err.into()),
|
||||
ReplyItem::Future(fut) => ComposeState::Handler(WaitingResponse {
|
||||
ReplyResult::Ok(resp) => RunMiddlewares::init(info, resp),
|
||||
ReplyResult::Err(err) => RunMiddlewares::init(info, err.into()),
|
||||
ReplyResult::Future(fut) => ComposeState::Handler(WaitingResponse {
|
||||
fut,
|
||||
_s: PhantomData,
|
||||
}),
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
}
|
||||
}
|
||||
|
||||
|
11
src/test.rs
11
src/test.rs
@ -21,7 +21,7 @@ use application::{App, HttpApplication};
|
||||
use body::Binary;
|
||||
use client::{ClientConnector, ClientRequest, ClientRequestBuilder};
|
||||
use error::Error;
|
||||
use handler::{Handler, ReplyItem, Responder};
|
||||
use handler::{Handler, ReplyResult, Responder};
|
||||
use header::{Header, IntoHeaderValue};
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
@ -601,10 +601,9 @@ impl<S> TestRequest<S> {
|
||||
|
||||
match resp.respond_to(req.drop_state()) {
|
||||
Ok(resp) => match resp.into().into() {
|
||||
ReplyItem::Message(resp) => Ok(resp),
|
||||
ReplyItem::Error(err) => Ok(err.into()),
|
||||
ReplyItem::Future(_) => panic!("Async handler is not supported."),
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
ReplyResult::Ok(resp) => Ok(resp),
|
||||
ReplyResult::Err(err) => Ok(err.into()),
|
||||
ReplyResult::Future(_) => panic!("Async handler is not supported."),
|
||||
},
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
@ -628,7 +627,7 @@ impl<S> TestRequest<S> {
|
||||
match core.run(fut) {
|
||||
Ok(r) => match r.respond_to(req.drop_state()) {
|
||||
Ok(reply) => match reply.into().into() {
|
||||
ReplyItem::Message(resp) => Ok(resp),
|
||||
ReplyResult::Ok(resp) => Ok(resp),
|
||||
_ => panic!("Nested async replies are not supported"),
|
||||
},
|
||||
Err(e) => Err(e),
|
||||
|
152
src/with.rs
152
src/with.rs
@ -5,7 +5,7 @@ use std::ops::{Deref, DerefMut};
|
||||
use std::rc::Rc;
|
||||
|
||||
use error::Error;
|
||||
use handler::{FromRequest, Handler, Reply, ReplyItem, Responder};
|
||||
use handler::{FromRequest, Handler, Reply, ReplyResult, Responder};
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
|
||||
@ -134,15 +134,14 @@ where
|
||||
|
||||
let item = if !self.started {
|
||||
self.started = true;
|
||||
let reply = T::from_request(&mut self.req, self.cfg.as_ref()).into();
|
||||
let reply = T::from_request(&self.req, self.cfg.as_ref()).into();
|
||||
match reply.into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(msg) => msg,
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(msg) => msg,
|
||||
ReplyResult::Future(fut) => {
|
||||
self.fut1 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
}
|
||||
} else {
|
||||
match self.fut1.as_mut().unwrap().poll()? {
|
||||
@ -158,13 +157,12 @@ where
|
||||
};
|
||||
|
||||
match item.into() {
|
||||
ReplyItem::Error(err) => Err(err),
|
||||
ReplyItem::Message(resp) => Ok(Async::Ready(resp)),
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => Err(err),
|
||||
ReplyResult::Ok(resp) => Ok(Async::Ready(resp)),
|
||||
ReplyResult::Future(fut) => {
|
||||
self.fut2 = Some(fut);
|
||||
self.poll()
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -268,39 +266,36 @@ where
|
||||
|
||||
if !self.started {
|
||||
self.started = true;
|
||||
let reply = T1::from_request(&mut self.req, self.cfg1.as_ref()).into();
|
||||
let reply = T1::from_request(&self.req, self.cfg1.as_ref()).into();
|
||||
let item1 = match reply.into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(msg) => msg,
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(msg) => msg,
|
||||
ReplyResult::Future(fut) => {
|
||||
self.fut1 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
};
|
||||
|
||||
let reply = T2::from_request(&mut self.req, self.cfg2.as_ref()).into();
|
||||
let reply = T2::from_request(&self.req, self.cfg2.as_ref()).into();
|
||||
let item2 = match reply.into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(msg) => msg,
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(msg) => msg,
|
||||
ReplyResult::Future(fut) => {
|
||||
self.item = Some(item1);
|
||||
self.fut2 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
};
|
||||
|
||||
let hnd: &mut F = unsafe { &mut *self.hnd.get() };
|
||||
match (*hnd)(item1, item2).respond_to(self.req.drop_state()) {
|
||||
Ok(item) => match item.into().into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyResult::Future(fut) => {
|
||||
self.fut3 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
},
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
@ -309,29 +304,26 @@ where
|
||||
if self.fut1.is_some() {
|
||||
match self.fut1.as_mut().unwrap().poll()? {
|
||||
Async::Ready(item) => {
|
||||
let reply =
|
||||
T2::from_request(&mut self.req, self.cfg2.as_ref()).into();
|
||||
let reply = T2::from_request(&self.req, self.cfg2.as_ref()).into();
|
||||
let item2 = match reply.into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(msg) => msg,
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(msg) => msg,
|
||||
ReplyResult::Future(fut) => {
|
||||
self.item = Some(item);
|
||||
self.fut2 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
};
|
||||
|
||||
let hnd: &mut F = unsafe { &mut *self.hnd.get() };
|
||||
match (*hnd)(item, item2).respond_to(self.req.drop_state()) {
|
||||
Ok(item) => match item.into().into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyResult::Future(fut) => {
|
||||
self.fut3 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
},
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
@ -354,10 +346,9 @@ where
|
||||
};
|
||||
|
||||
match item.into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyItem::Future(fut) => self.fut3 = Some(fut),
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyResult::Future(fut) => self.fut3 = Some(fut),
|
||||
}
|
||||
|
||||
self.poll()
|
||||
@ -480,52 +471,48 @@ where
|
||||
|
||||
if !self.started {
|
||||
self.started = true;
|
||||
let reply = T1::from_request(&mut self.req, self.cfg1.as_ref()).into();
|
||||
let reply = T1::from_request(&self.req, self.cfg1.as_ref()).into();
|
||||
let item1 = match reply.into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(msg) => msg,
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(msg) => msg,
|
||||
ReplyResult::Future(fut) => {
|
||||
self.fut1 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
};
|
||||
|
||||
let reply = T2::from_request(&mut self.req, self.cfg2.as_ref()).into();
|
||||
let reply = T2::from_request(&self.req, self.cfg2.as_ref()).into();
|
||||
let item2 = match reply.into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(msg) => msg,
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(msg) => msg,
|
||||
ReplyResult::Future(fut) => {
|
||||
self.item1 = Some(item1);
|
||||
self.fut2 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
};
|
||||
|
||||
let reply = T3::from_request(&mut self.req, self.cfg3.as_ref()).into();
|
||||
let reply = T3::from_request(&self.req, self.cfg3.as_ref()).into();
|
||||
let item3 = match reply.into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(msg) => msg,
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(msg) => msg,
|
||||
ReplyResult::Future(fut) => {
|
||||
self.item1 = Some(item1);
|
||||
self.item2 = Some(item2);
|
||||
self.fut3 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
};
|
||||
|
||||
let hnd: &mut F = unsafe { &mut *self.hnd.get() };
|
||||
match (*hnd)(item1, item2, item3).respond_to(self.req.drop_state()) {
|
||||
Ok(item) => match item.into().into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyResult::Future(fut) => {
|
||||
self.fut4 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
},
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
@ -536,42 +523,37 @@ where
|
||||
Async::Ready(item) => {
|
||||
self.item1 = Some(item);
|
||||
self.fut1.take();
|
||||
let reply =
|
||||
T2::from_request(&mut self.req, self.cfg2.as_ref()).into();
|
||||
let reply = T2::from_request(&self.req, self.cfg2.as_ref()).into();
|
||||
let item2 = match reply.into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(msg) => msg,
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(msg) => msg,
|
||||
ReplyResult::Future(fut) => {
|
||||
self.fut2 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
};
|
||||
|
||||
let reply =
|
||||
T3::from_request(&mut self.req, self.cfg3.as_ref()).into();
|
||||
let reply = T3::from_request(&self.req, self.cfg3.as_ref()).into();
|
||||
let item3 = match reply.into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(msg) => msg,
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(msg) => msg,
|
||||
ReplyResult::Future(fut) => {
|
||||
self.item2 = Some(item2);
|
||||
self.fut3 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
};
|
||||
let hnd: &mut F = unsafe { &mut *self.hnd.get() };
|
||||
match (*hnd)(self.item1.take().unwrap(), item2, item3)
|
||||
.respond_to(self.req.drop_state())
|
||||
{
|
||||
Ok(item) => match item.into().into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyResult::Future(fut) => {
|
||||
self.fut4 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
},
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
@ -584,30 +566,27 @@ where
|
||||
match self.fut2.as_mut().unwrap().poll()? {
|
||||
Async::Ready(item) => {
|
||||
self.fut2.take();
|
||||
let reply =
|
||||
T3::from_request(&mut self.req, self.cfg3.as_ref()).into();
|
||||
let reply = T3::from_request(&self.req, self.cfg3.as_ref()).into();
|
||||
let item3 = match reply.into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(msg) => msg,
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(msg) => msg,
|
||||
ReplyResult::Future(fut) => {
|
||||
self.item2 = Some(item);
|
||||
self.fut3 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
};
|
||||
let hnd: &mut F = unsafe { &mut *self.hnd.get() };
|
||||
match (*hnd)(self.item1.take().unwrap(), item, item3)
|
||||
.respond_to(self.req.drop_state())
|
||||
{
|
||||
Ok(item) => match item.into().into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyItem::Future(fut) => {
|
||||
ReplyResult::Err(err) => return Err(err),
|
||||
ReplyResult::Ok(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyResult::Future(fut) => {
|
||||
self.fut4 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
},
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
@ -633,10 +612,9 @@ where
|
||||
};
|
||||
|
||||
match item.into() {
|
||||
ReplyItem::Error(err) => return Ok(Async::Ready(err.into())),
|
||||
ReplyItem::Message(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyItem::Future(fut) => self.fut4 = Some(fut),
|
||||
ReplyItem::None => panic!("use after resolve"),
|
||||
ReplyResult::Err(err) => return Ok(Async::Ready(err.into())),
|
||||
ReplyResult::Ok(resp) => return Ok(Async::Ready(resp)),
|
||||
ReplyResult::Future(fut) => self.fut4 = Some(fut),
|
||||
}
|
||||
|
||||
self.poll()
|
||||
|
Loading…
Reference in New Issue
Block a user