mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-30 18:34:36 +01:00
refactor FromRequest trait
This commit is contained in:
parent
195246573e
commit
8d65468c58
@ -11,6 +11,10 @@
|
||||
* `HttpRequest::extensions()` returns read only reference to the request's Extension
|
||||
`HttpRequest::extensions_mut()` returns mutable reference.
|
||||
|
||||
* `FromRequest::from_request()` accepts mutable reference to a request
|
||||
|
||||
* `FromRequest::Result` has to implement `Into<Reply<Self>>`
|
||||
|
||||
|
||||
## Migration from 0.4 to 0.5
|
||||
|
||||
|
@ -6,6 +6,7 @@ use handler::{FromRequest, Handler, Reply, Responder, RouteHandler, WrapHandler}
|
||||
use header::ContentEncoding;
|
||||
use http::Method;
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
use middleware::Middleware;
|
||||
use pipeline::{HandlerType, Pipeline, PipelineHandler};
|
||||
use resource::ResourceHandler;
|
||||
@ -36,7 +37,9 @@ impl<S: 'static> PipelineHandler<S> for Inner<S> {
|
||||
self.encoding
|
||||
}
|
||||
|
||||
fn handle(&mut self, req: HttpRequest<S>, htype: HandlerType) -> Reply {
|
||||
fn handle(
|
||||
&mut self, req: HttpRequest<S>, htype: HandlerType,
|
||||
) -> Reply<HttpResponse> {
|
||||
match htype {
|
||||
HandlerType::Normal(idx) => {
|
||||
self.resources[idx].handle(req, Some(&mut self.default))
|
||||
@ -87,7 +90,7 @@ impl<S: 'static> HttpApplication<S> {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn run(&mut self, mut req: HttpRequest<S>) -> Reply {
|
||||
pub(crate) fn run(&mut self, mut req: HttpRequest<S>) -> Reply<HttpResponse> {
|
||||
let tp = self.get_handler(&mut req);
|
||||
unsafe { &mut *self.inner.get() }.handle(req, tp)
|
||||
}
|
||||
@ -669,24 +672,18 @@ mod tests {
|
||||
|
||||
let req = TestRequest::with_uri("/test").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
|
||||
let req = TestRequest::with_uri("/blah").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::NOT_FOUND
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||
|
||||
let mut app = App::new()
|
||||
.default_resource(|r| r.f(|_| HttpResponse::MethodNotAllowed()))
|
||||
.finish();
|
||||
let req = TestRequest::with_uri("/blah").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::METHOD_NOT_ALLOWED
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::METHOD_NOT_ALLOWED);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -706,7 +703,7 @@ mod tests {
|
||||
let req =
|
||||
HttpRequest::default().with_state(Rc::clone(&app.state), app.router.clone());
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -740,29 +737,23 @@ mod tests {
|
||||
|
||||
let req = TestRequest::with_uri("/test").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
|
||||
let req = TestRequest::with_uri("/test/").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
|
||||
let req = TestRequest::with_uri("/test/app").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
|
||||
let req = TestRequest::with_uri("/testapp").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::NOT_FOUND
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||
|
||||
let req = TestRequest::with_uri("/blah").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::NOT_FOUND
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -773,29 +764,23 @@ mod tests {
|
||||
|
||||
let req = TestRequest::with_uri("/test").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
|
||||
let req = TestRequest::with_uri("/test/").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
|
||||
let req = TestRequest::with_uri("/test/app").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
|
||||
let req = TestRequest::with_uri("/testapp").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::NOT_FOUND
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||
|
||||
let req = TestRequest::with_uri("/blah").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::NOT_FOUND
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -807,29 +792,23 @@ mod tests {
|
||||
|
||||
let req = TestRequest::with_uri("/prefix/test").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
|
||||
let req = TestRequest::with_uri("/prefix/test/").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
|
||||
let req = TestRequest::with_uri("/prefix/test/app").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
|
||||
let req = TestRequest::with_uri("/prefix/testapp").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::NOT_FOUND
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||
|
||||
let req = TestRequest::with_uri("/prefix/blah").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::NOT_FOUND
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -847,25 +826,19 @@ mod tests {
|
||||
.method(Method::GET)
|
||||
.finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
|
||||
let req = TestRequest::with_uri("/test")
|
||||
.method(Method::POST)
|
||||
.finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::CREATED
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::CREATED);
|
||||
|
||||
let req = TestRequest::with_uri("/test")
|
||||
.method(Method::HEAD)
|
||||
.finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::NOT_FOUND
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -877,36 +850,27 @@ mod tests {
|
||||
|
||||
let req = TestRequest::with_uri("/test").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::NOT_FOUND
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||
|
||||
let req = TestRequest::with_uri("/app/test").finish();
|
||||
let resp = app.run(req.clone());
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
assert_eq!(req.prefix_len(), 9);
|
||||
|
||||
let req = TestRequest::with_uri("/app/test/").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
|
||||
let req = TestRequest::with_uri("/app/test/app").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
|
||||
let req = TestRequest::with_uri("/app/testapp").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::NOT_FOUND
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||
|
||||
let req = TestRequest::with_uri("/app/blah").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::NOT_FOUND
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
131
src/extractor.rs
131
src/extractor.rs
@ -4,14 +4,14 @@ use std::str;
|
||||
use bytes::Bytes;
|
||||
use encoding::all::UTF_8;
|
||||
use encoding::types::{DecoderTrap, Encoding};
|
||||
use futures::future::{result, Future, FutureResult};
|
||||
use futures::future::Future;
|
||||
use mime::Mime;
|
||||
use serde::de::{self, DeserializeOwned};
|
||||
use serde_urlencoded;
|
||||
|
||||
use de::PathDeserializer;
|
||||
use error::{Error, ErrorBadRequest};
|
||||
use handler::{Either, FromRequest};
|
||||
use handler::FromRequest;
|
||||
use httpmessage::{HttpMessage, MessageBody, UrlEncoded};
|
||||
use httprequest::HttpRequest;
|
||||
|
||||
@ -102,16 +102,14 @@ where
|
||||
S: 'static,
|
||||
{
|
||||
type Config = ();
|
||||
type Result = FutureResult<Self, Error>;
|
||||
type Result = Result<Self, Error>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
fn from_request(req: &mut HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
let req = req.clone();
|
||||
result(
|
||||
de::Deserialize::deserialize(PathDeserializer::new(&req))
|
||||
.map_err(|e| e.into())
|
||||
.map(|inner| Path { inner }),
|
||||
)
|
||||
.map(|inner| Path { inner })
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,16 +170,14 @@ where
|
||||
S: 'static,
|
||||
{
|
||||
type Config = ();
|
||||
type Result = FutureResult<Self, Error>;
|
||||
type Result = Result<Self, Error>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
fn from_request(req: &mut HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
let req = req.clone();
|
||||
result(
|
||||
serde_urlencoded::from_str::<T>(req.query_string())
|
||||
.map_err(|e| e.into())
|
||||
.map(Query),
|
||||
)
|
||||
.map(Query)
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,7 +241,7 @@ where
|
||||
type Result = Box<Future<Item = Self, Error = Error>>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
fn from_request(req: &mut HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
Box::new(
|
||||
UrlEncoded::new(req.clone())
|
||||
.limit(cfg.limit)
|
||||
@ -327,17 +323,14 @@ impl Default for FormConfig {
|
||||
/// ```
|
||||
impl<S: 'static> FromRequest<S> for Bytes {
|
||||
type Config = PayloadConfig;
|
||||
type Result =
|
||||
Either<FutureResult<Self, Error>, Box<Future<Item = Self, Error = Error>>>;
|
||||
type Result = Result<Box<Future<Item = Self, Error = Error>>, Error>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
fn from_request(req: &mut HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
// check content-type
|
||||
if let Err(e) = cfg.check_mimetype(req) {
|
||||
return Either::A(result(Err(e)));
|
||||
}
|
||||
cfg.check_mimetype(req)?;
|
||||
|
||||
Either::B(Box::new(
|
||||
Ok(Box::new(
|
||||
MessageBody::new(req.clone())
|
||||
.limit(cfg.limit)
|
||||
.from_err(),
|
||||
@ -374,27 +367,17 @@ impl<S: 'static> FromRequest<S> for Bytes {
|
||||
/// ```
|
||||
impl<S: 'static> FromRequest<S> for String {
|
||||
type Config = PayloadConfig;
|
||||
type Result =
|
||||
Either<FutureResult<String, Error>, Box<Future<Item = String, Error = Error>>>;
|
||||
type Result = Result<Box<Future<Item = String, Error = Error>>, Error>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
fn from_request(req: &mut HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
// check content-type
|
||||
if let Err(e) = cfg.check_mimetype(req) {
|
||||
return Either::A(result(Err(e)));
|
||||
}
|
||||
cfg.check_mimetype(req)?;
|
||||
|
||||
// check charset
|
||||
let encoding = match req.encoding() {
|
||||
Err(_) => {
|
||||
return Either::A(result(Err(ErrorBadRequest(
|
||||
"Unknown request charset",
|
||||
))))
|
||||
}
|
||||
Ok(encoding) => encoding,
|
||||
};
|
||||
let encoding = req.encoding()?;
|
||||
|
||||
Either::B(Box::new(
|
||||
Ok(Box::new(
|
||||
MessageBody::new(req.clone())
|
||||
.limit(cfg.limit)
|
||||
.from_err()
|
||||
@ -488,7 +471,11 @@ mod tests {
|
||||
req.payload_mut()
|
||||
.unread_data(Bytes::from_static(b"hello=world"));
|
||||
|
||||
match Bytes::from_request(&req, &cfg).poll().unwrap() {
|
||||
match Bytes::from_request(&mut req, &cfg)
|
||||
.unwrap()
|
||||
.poll()
|
||||
.unwrap()
|
||||
{
|
||||
Async::Ready(s) => {
|
||||
assert_eq!(s, Bytes::from_static(b"hello=world"));
|
||||
}
|
||||
@ -503,7 +490,11 @@ mod tests {
|
||||
req.payload_mut()
|
||||
.unread_data(Bytes::from_static(b"hello=world"));
|
||||
|
||||
match String::from_request(&req, &cfg).poll().unwrap() {
|
||||
match String::from_request(&mut req, &cfg)
|
||||
.unwrap()
|
||||
.poll()
|
||||
.unwrap()
|
||||
{
|
||||
Async::Ready(s) => {
|
||||
assert_eq!(s, "hello=world");
|
||||
}
|
||||
@ -523,7 +514,10 @@ mod tests {
|
||||
|
||||
let mut cfg = FormConfig::default();
|
||||
cfg.limit(4096);
|
||||
match Form::<Info>::from_request(&req, &cfg).poll().unwrap() {
|
||||
match Form::<Info>::from_request(&mut req, &cfg)
|
||||
.poll()
|
||||
.unwrap()
|
||||
{
|
||||
Async::Ready(s) => {
|
||||
assert_eq!(s.hello, "world");
|
||||
}
|
||||
@ -580,69 +574,31 @@ mod tests {
|
||||
let (router, _) = Router::new("", ServerSettings::default(), routes);
|
||||
assert!(router.recognize(&mut req).is_some());
|
||||
|
||||
match Path::<MyStruct>::from_request(&req, &())
|
||||
.poll()
|
||||
.unwrap()
|
||||
{
|
||||
Async::Ready(s) => {
|
||||
let s = Path::<MyStruct>::from_request(&mut req, &()).unwrap();
|
||||
assert_eq!(s.key, "name");
|
||||
assert_eq!(s.value, "user1");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
match Path::<(String, String)>::from_request(&req, &())
|
||||
.poll()
|
||||
.unwrap()
|
||||
{
|
||||
Async::Ready(s) => {
|
||||
let s = Path::<(String, String)>::from_request(&mut req, &()).unwrap();
|
||||
assert_eq!(s.0, "name");
|
||||
assert_eq!(s.1, "user1");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
match Query::<Id>::from_request(&req, &()).poll().unwrap() {
|
||||
Async::Ready(s) => {
|
||||
let s = Query::<Id>::from_request(&mut req, &()).unwrap();
|
||||
assert_eq!(s.id, "test");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
let mut req = TestRequest::with_uri("/name/32/").finish();
|
||||
assert!(router.recognize(&mut req).is_some());
|
||||
|
||||
match Path::<Test2>::from_request(&req, &()).poll().unwrap() {
|
||||
Async::Ready(s) => {
|
||||
let s = Path::<Test2>::from_request(&mut req, &()).unwrap();
|
||||
assert_eq!(s.as_ref().key, "name");
|
||||
assert_eq!(s.value, 32);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
match Path::<(String, u8)>::from_request(&req, &())
|
||||
.poll()
|
||||
.unwrap()
|
||||
{
|
||||
Async::Ready(s) => {
|
||||
let s = Path::<(String, u8)>::from_request(&mut req, &()).unwrap();
|
||||
assert_eq!(s.0, "name");
|
||||
assert_eq!(s.1, 32);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
match Path::<Vec<String>>::from_request(&req, &())
|
||||
.poll()
|
||||
.unwrap()
|
||||
{
|
||||
Async::Ready(s) => {
|
||||
assert_eq!(
|
||||
s.into_inner(),
|
||||
vec!["name".to_owned(), "32".to_owned()]
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
let res = Path::<Vec<String>>::from_request(&mut req, &()).unwrap();
|
||||
assert_eq!(res[0], "name".to_owned());
|
||||
assert_eq!(res[1], "32".to_owned());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -656,11 +612,6 @@ mod tests {
|
||||
let mut req = TestRequest::with_uri("/32/").finish();
|
||||
assert!(router.recognize(&mut req).is_some());
|
||||
|
||||
match Path::<i8>::from_request(&req, &()).poll().unwrap() {
|
||||
Async::Ready(s) => {
|
||||
assert_eq!(s.into_inner(), 32);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
assert_eq!(*Path::<i8>::from_request(&mut req, &()).unwrap(), 32);
|
||||
}
|
||||
}
|
||||
|
14
src/fs.rs
14
src/fs.rs
@ -565,7 +565,7 @@ impl<S: 'static> StaticFiles<S> {
|
||||
}
|
||||
|
||||
impl<S: 'static> Handler<S> for StaticFiles<S> {
|
||||
type Result = Result<Reply, Error>;
|
||||
type Result = Result<Reply<HttpResponse>, Error>;
|
||||
|
||||
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result {
|
||||
if !self.accessible {
|
||||
@ -755,7 +755,7 @@ mod tests {
|
||||
let resp = st.handle(HttpRequest::default())
|
||||
.respond_to(HttpRequest::default())
|
||||
.unwrap();
|
||||
let resp = resp.as_response().expect("HTTP Response");
|
||||
let resp = resp.as_msg();
|
||||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||
|
||||
st.accessible = true;
|
||||
@ -763,7 +763,7 @@ mod tests {
|
||||
let resp = st.handle(HttpRequest::default())
|
||||
.respond_to(HttpRequest::default())
|
||||
.unwrap();
|
||||
let resp = resp.as_response().expect("HTTP Response");
|
||||
let resp = resp.as_msg();
|
||||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||
|
||||
let mut req = HttpRequest::default();
|
||||
@ -773,7 +773,7 @@ mod tests {
|
||||
let resp = st.handle(req)
|
||||
.respond_to(HttpRequest::default())
|
||||
.unwrap();
|
||||
let resp = resp.as_response().expect("HTTP Response");
|
||||
let resp = resp.as_msg();
|
||||
assert_eq!(
|
||||
resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||
"text/html; charset=utf-8"
|
||||
@ -791,7 +791,7 @@ mod tests {
|
||||
let resp = st.handle(req)
|
||||
.respond_to(HttpRequest::default())
|
||||
.unwrap();
|
||||
let resp = resp.as_response().expect("HTTP Response");
|
||||
let resp = resp.as_msg();
|
||||
assert_eq!(resp.status(), StatusCode::FOUND);
|
||||
assert_eq!(
|
||||
resp.headers().get(header::LOCATION).unwrap(),
|
||||
@ -804,7 +804,7 @@ mod tests {
|
||||
let resp = st.handle(req)
|
||||
.respond_to(HttpRequest::default())
|
||||
.unwrap();
|
||||
let resp = resp.as_response().expect("HTTP Response");
|
||||
let resp = resp.as_msg();
|
||||
assert_eq!(resp.status(), StatusCode::FOUND);
|
||||
assert_eq!(
|
||||
resp.headers().get(header::LOCATION).unwrap(),
|
||||
@ -821,7 +821,7 @@ mod tests {
|
||||
let resp = st.handle(req)
|
||||
.respond_to(HttpRequest::default())
|
||||
.unwrap();
|
||||
let resp = resp.as_response().expect("HTTP Response");
|
||||
let resp = resp.as_msg();
|
||||
assert_eq!(resp.status(), StatusCode::FOUND);
|
||||
assert_eq!(
|
||||
resp.headers().get(header::LOCATION).unwrap(),
|
||||
|
114
src/handler.rs
114
src/handler.rs
@ -1,4 +1,4 @@
|
||||
use futures::future::{err, ok, Future, FutureResult};
|
||||
use futures::future::{err, ok, Future};
|
||||
use futures::Poll;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Deref;
|
||||
@ -22,7 +22,7 @@ pub trait Handler<S>: 'static {
|
||||
/// Types that implement this trait can be used as the return type of a handler.
|
||||
pub trait Responder {
|
||||
/// The associated item which can be returned.
|
||||
type Item: Into<Reply>;
|
||||
type Item: Into<Reply<HttpResponse>>;
|
||||
|
||||
/// The associated error which can be returned.
|
||||
type Error: Into<Error>;
|
||||
@ -42,10 +42,10 @@ where
|
||||
type Config: Default;
|
||||
|
||||
/// Future that resolves to a Self
|
||||
type Result: Future<Item = Self, Error = Error>;
|
||||
type Result: Into<Reply<Self>>;
|
||||
|
||||
/// Convert request to a Self
|
||||
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result;
|
||||
fn from_request(req: &mut HttpRequest<S>, cfg: &Self::Config) -> Self::Result;
|
||||
}
|
||||
|
||||
/// Combines two different responder types into a single type
|
||||
@ -88,10 +88,10 @@ where
|
||||
A: Responder,
|
||||
B: Responder,
|
||||
{
|
||||
type Item = Reply;
|
||||
type Item = Reply<HttpResponse>;
|
||||
type Error = Error;
|
||||
|
||||
fn respond_to(self, req: HttpRequest) -> Result<Reply, Error> {
|
||||
fn respond_to(self, req: HttpRequest) -> Result<Reply<HttpResponse>, Error> {
|
||||
match self {
|
||||
Either::A(a) => match a.respond_to(req) {
|
||||
Ok(val) => Ok(val.into()),
|
||||
@ -177,66 +177,86 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents response process.
|
||||
pub struct Reply(ReplyItem);
|
||||
/// Represents reply process.
|
||||
///
|
||||
/// Reply could be in tree different forms.
|
||||
/// * 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(crate) enum ReplyItem {
|
||||
Message(HttpResponse),
|
||||
Future(Box<Future<Item = HttpResponse, Error = Error>>),
|
||||
pub(crate) enum ReplyItem<T> {
|
||||
Error(Error),
|
||||
Message(T),
|
||||
Future(Box<Future<Item = T, Error = Error>>),
|
||||
}
|
||||
|
||||
impl Reply {
|
||||
impl<T> Reply<T> {
|
||||
/// Create async response
|
||||
#[inline]
|
||||
pub fn async<F>(fut: F) -> Reply
|
||||
pub fn async<F>(fut: F) -> Reply<T>
|
||||
where
|
||||
F: Future<Item = HttpResponse, Error = Error> + 'static,
|
||||
F: Future<Item = T, Error = Error> + 'static,
|
||||
{
|
||||
Reply(ReplyItem::Future(Box::new(fut)))
|
||||
}
|
||||
|
||||
/// Send response
|
||||
#[inline]
|
||||
pub fn response<R: Into<HttpResponse>>(response: R) -> Reply {
|
||||
pub fn response<R: Into<T>>(response: R) -> Reply<T> {
|
||||
Reply(ReplyItem::Message(response.into()))
|
||||
}
|
||||
|
||||
/// Send error
|
||||
#[inline]
|
||||
pub(crate) fn into(self) -> ReplyItem {
|
||||
pub fn error<R: Into<Error>>(err: R) -> Reply<T> {
|
||||
Reply(ReplyItem::Error(err.into()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn into(self) -> ReplyItem<T> {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn as_response(&self) -> Option<&HttpResponse> {
|
||||
pub(crate) fn as_msg(&self) -> &T {
|
||||
match self.0 {
|
||||
ReplyItem::Message(ref resp) => Some(resp),
|
||||
ReplyItem::Message(ref resp) => resp,
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn as_err(&self) -> Option<&Error> {
|
||||
match self.0 {
|
||||
ReplyItem::Error(ref err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Responder for Reply {
|
||||
type Item = Reply;
|
||||
impl Responder for Reply<HttpResponse> {
|
||||
type Item = Reply<HttpResponse>;
|
||||
type Error = Error;
|
||||
|
||||
fn respond_to(self, _: HttpRequest) -> Result<Reply, Error> {
|
||||
fn respond_to(self, _: HttpRequest) -> Result<Reply<HttpResponse>, Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Responder for HttpResponse {
|
||||
type Item = Reply;
|
||||
type Item = Reply<HttpResponse>;
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
fn respond_to(self, _: HttpRequest) -> Result<Reply, Error> {
|
||||
fn respond_to(self, _: HttpRequest) -> Result<Reply<HttpResponse>, Error> {
|
||||
Ok(Reply(ReplyItem::Message(self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HttpResponse> for Reply {
|
||||
impl<T> From<T> for Reply<T> {
|
||||
#[inline]
|
||||
fn from(resp: HttpResponse) -> Reply {
|
||||
fn from(resp: T) -> Reply<T> {
|
||||
Reply(ReplyItem::Message(resp))
|
||||
}
|
||||
}
|
||||
@ -256,29 +276,41 @@ impl<T: Responder, E: Into<Error>> Responder for Result<T, E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Into<Error>> From<Result<Reply, E>> for Reply {
|
||||
impl<T, E: Into<Error>> From<Result<Reply<T>, E>> for Reply<T> {
|
||||
#[inline]
|
||||
fn from(res: Result<Reply, E>) -> Self {
|
||||
fn from(res: Result<Reply<T>, E>) -> Self {
|
||||
match res {
|
||||
Ok(val) => val,
|
||||
Err(err) => Reply(ReplyItem::Message(err.into().into())),
|
||||
Err(err) => Reply(ReplyItem::Error(err.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Into<Error>> From<Result<HttpResponse, E>> for Reply {
|
||||
impl<T, E: Into<Error>> From<Result<T, E>> for Reply<T> {
|
||||
#[inline]
|
||||
fn from(res: Result<HttpResponse, E>) -> Self {
|
||||
fn from(res: Result<T, E>) -> Self {
|
||||
match res {
|
||||
Ok(val) => Reply(ReplyItem::Message(val)),
|
||||
Err(err) => Reply(ReplyItem::Message(err.into().into())),
|
||||
Err(err) => Reply(ReplyItem::Error(err.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<Future<Item = HttpResponse, Error = Error>>> for Reply {
|
||||
impl<T, E: Into<Error>> From<Result<Box<Future<Item = T, Error = Error>>, E>>
|
||||
for Reply<T>
|
||||
{
|
||||
#[inline]
|
||||
fn from(fut: Box<Future<Item = HttpResponse, Error = Error>>) -> Reply {
|
||||
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())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
@ -291,11 +323,11 @@ where
|
||||
I: Responder + 'static,
|
||||
E: Into<Error> + 'static,
|
||||
{
|
||||
type Item = Reply;
|
||||
type Item = Reply<HttpResponse>;
|
||||
type Error = Error;
|
||||
|
||||
#[inline]
|
||||
fn respond_to(self, req: HttpRequest) -> Result<Reply, Error> {
|
||||
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 {
|
||||
@ -310,7 +342,7 @@ where
|
||||
|
||||
/// Trait defines object that could be registered as resource route
|
||||
pub(crate) trait RouteHandler<S>: 'static {
|
||||
fn handle(&mut self, req: HttpRequest<S>) -> Reply;
|
||||
fn handle(&mut self, req: HttpRequest<S>) -> Reply<HttpResponse>;
|
||||
}
|
||||
|
||||
/// Route handler wrapper for Handler
|
||||
@ -344,7 +376,7 @@ where
|
||||
R: Responder + 'static,
|
||||
S: 'static,
|
||||
{
|
||||
fn handle(&mut self, req: HttpRequest<S>) -> Reply {
|
||||
fn handle(&mut self, req: HttpRequest<S>) -> Reply<HttpResponse> {
|
||||
let req2 = req.drop_state();
|
||||
match self.h.handle(req).respond_to(req2) {
|
||||
Ok(reply) => reply.into(),
|
||||
@ -390,7 +422,7 @@ where
|
||||
E: Into<Error> + 'static,
|
||||
S: 'static,
|
||||
{
|
||||
fn handle(&mut self, req: HttpRequest<S>) -> Reply {
|
||||
fn handle(&mut self, req: HttpRequest<S>) -> Reply<HttpResponse> {
|
||||
let req2 = req.drop_state();
|
||||
let fut = (self.h)(req).map_err(|e| e.into()).then(move |r| {
|
||||
match r.respond_to(req2) {
|
||||
@ -449,10 +481,10 @@ impl<S> Deref for State<S> {
|
||||
|
||||
impl<S: 'static> FromRequest<S> for State<S> {
|
||||
type Config = ();
|
||||
type Result = FutureResult<Self, Error>;
|
||||
type Result = State<S>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
ok(State(req.clone()))
|
||||
fn from_request(req: &mut HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
State(req.clone()).into()
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ mod tests {
|
||||
for (path, target, code) in params {
|
||||
let req = app.prepare_request(TestRequest::with_uri(path).finish());
|
||||
let resp = app.run(req);
|
||||
let r = resp.as_response().unwrap();
|
||||
let r = resp.as_msg();
|
||||
assert_eq!(r.status(), code);
|
||||
if !target.is_empty() {
|
||||
assert_eq!(
|
||||
@ -260,7 +260,7 @@ mod tests {
|
||||
for (path, code) in params {
|
||||
let req = app.prepare_request(TestRequest::with_uri(path).finish());
|
||||
let resp = app.run(req);
|
||||
let r = resp.as_response().unwrap();
|
||||
let r = resp.as_msg();
|
||||
assert_eq!(r.status(), code);
|
||||
}
|
||||
}
|
||||
@ -351,7 +351,7 @@ mod tests {
|
||||
for (path, target, code) in params {
|
||||
let req = app.prepare_request(TestRequest::with_uri(path).finish());
|
||||
let resp = app.run(req);
|
||||
let r = resp.as_response().unwrap();
|
||||
let r = resp.as_msg();
|
||||
assert_eq!(r.status(), code);
|
||||
if !target.is_empty() {
|
||||
assert_eq!(
|
||||
@ -535,7 +535,7 @@ mod tests {
|
||||
for (path, target, code) in params {
|
||||
let req = app.prepare_request(TestRequest::with_uri(path).finish());
|
||||
let resp = app.run(req);
|
||||
let r = resp.as_response().unwrap();
|
||||
let r = resp.as_msg();
|
||||
assert_eq!(r.status(), code);
|
||||
if !target.is_empty() {
|
||||
assert_eq!(
|
||||
|
@ -1,20 +1,20 @@
|
||||
//! HTTP Request message related code.
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ptr))]
|
||||
use bytes::Bytes;
|
||||
use cookie::Cookie;
|
||||
use failure;
|
||||
use futures::future::{result, FutureResult};
|
||||
use futures::{Async, Poll, Stream};
|
||||
use futures_cpupool::CpuPool;
|
||||
use http::{header, Extensions, HeaderMap, Method, StatusCode, Uri, Version};
|
||||
use std::net::SocketAddr;
|
||||
use std::rc::Rc;
|
||||
use std::{cmp, fmt, io, mem, str};
|
||||
|
||||
use bytes::Bytes;
|
||||
use cookie::Cookie;
|
||||
use failure;
|
||||
use futures::{Async, Poll, Stream};
|
||||
use futures_cpupool::CpuPool;
|
||||
use http::{header, Extensions, HeaderMap, Method, StatusCode, Uri, Version};
|
||||
use tokio_io::AsyncRead;
|
||||
use url::{form_urlencoded, Url};
|
||||
|
||||
use body::Body;
|
||||
use error::{CookieParseError, Error, PayloadError, UrlGenerationError};
|
||||
use error::{CookieParseError, PayloadError, UrlGenerationError};
|
||||
use handler::FromRequest;
|
||||
use httpmessage::HttpMessage;
|
||||
use httpresponse::{HttpResponse, HttpResponseBuilder};
|
||||
@ -502,11 +502,11 @@ impl<S> Clone for HttpRequest<S> {
|
||||
|
||||
impl<S: 'static> FromRequest<S> for HttpRequest<S> {
|
||||
type Config = ();
|
||||
type Result = FutureResult<Self, Error>;
|
||||
type Result = Self;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
result(Ok(req.clone()))
|
||||
fn from_request(req: &mut HttpRequest<S>, _: &Self::Config) -> Self::Result {
|
||||
req.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
18
src/json.rs
18
src/json.rs
@ -136,7 +136,7 @@ where
|
||||
type Result = Box<Future<Item = Self, Error = Error>>;
|
||||
|
||||
#[inline]
|
||||
fn from_request(req: &HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
fn from_request(req: &mut HttpRequest<S>, cfg: &Self::Config) -> Self::Result {
|
||||
let req = req.clone();
|
||||
let err = Rc::clone(&cfg.ehandler);
|
||||
Box::new(
|
||||
@ -417,13 +417,7 @@ mod tests {
|
||||
let mut handler = With::new(|data: Json<MyObject>| data, cfg);
|
||||
|
||||
let req = HttpRequest::default();
|
||||
let err = handler
|
||||
.handle(req)
|
||||
.as_response()
|
||||
.unwrap()
|
||||
.error()
|
||||
.is_some();
|
||||
assert!(err);
|
||||
assert!(handler.handle(req).as_err().is_some());
|
||||
|
||||
let mut req = HttpRequest::default();
|
||||
req.headers_mut().insert(
|
||||
@ -436,12 +430,6 @@ mod tests {
|
||||
);
|
||||
req.payload_mut()
|
||||
.unread_data(Bytes::from_static(b"{\"name\": \"test\"}"));
|
||||
let ok = handler
|
||||
.handle(req)
|
||||
.as_response()
|
||||
.unwrap()
|
||||
.error()
|
||||
.is_none();
|
||||
assert!(ok)
|
||||
assert!(handler.handle(req).as_err().is_none())
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,8 @@ pub(crate) enum HandlerType {
|
||||
pub(crate) trait PipelineHandler<S> {
|
||||
fn encoding(&self) -> ContentEncoding;
|
||||
|
||||
fn handle(&mut self, req: HttpRequest<S>, htype: HandlerType) -> Reply;
|
||||
fn handle(&mut self, req: HttpRequest<S>, htype: HandlerType)
|
||||
-> Reply<HttpResponse>;
|
||||
}
|
||||
|
||||
pub(crate) struct Pipeline<S, H>(PipelineInfo<S>, PipelineState<S, H>);
|
||||
@ -319,8 +320,11 @@ struct WaitingResponse<S, H> {
|
||||
|
||||
impl<S: 'static, H> WaitingResponse<S, H> {
|
||||
#[inline]
|
||||
fn init(info: &mut PipelineInfo<S>, reply: Reply) -> PipelineState<S, H> {
|
||||
fn init(
|
||||
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 {
|
||||
fut,
|
||||
|
@ -198,7 +198,7 @@ impl<S: 'static> ResourceHandler<S> {
|
||||
|
||||
pub(crate) fn handle(
|
||||
&mut self, mut req: HttpRequest<S>, default: Option<&mut ResourceHandler<S>>,
|
||||
) -> Reply {
|
||||
) -> Reply<HttpResponse> {
|
||||
for route in &mut self.routes {
|
||||
if route.check(&mut req) {
|
||||
return if self.middlewares.is_empty() {
|
||||
|
@ -45,14 +45,14 @@ impl<S: 'static> Route<S> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn handle(&mut self, req: HttpRequest<S>) -> Reply {
|
||||
pub(crate) fn handle(&mut self, req: HttpRequest<S>) -> Reply<HttpResponse> {
|
||||
self.handler.handle(req)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn compose(
|
||||
&mut self, req: HttpRequest<S>, mws: Rc<Vec<Box<Middleware<S>>>>,
|
||||
) -> Reply {
|
||||
) -> Reply<HttpResponse> {
|
||||
Reply::async(Compose::new(req, mws, self.handler.clone()))
|
||||
}
|
||||
|
||||
@ -243,7 +243,7 @@ impl<S: 'static> InnerHandler<S> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn handle(&self, req: HttpRequest<S>) -> Reply {
|
||||
pub fn handle(&self, req: HttpRequest<S>) -> Reply<HttpResponse> {
|
||||
// reason: handler is unique per thread, handler get called from async code only
|
||||
let h = unsafe { &mut *self.0.as_ref().get() };
|
||||
h.handle(req)
|
||||
@ -415,8 +415,9 @@ struct WaitingResponse<S> {
|
||||
|
||||
impl<S: 'static> WaitingResponse<S> {
|
||||
#[inline]
|
||||
fn init(info: &mut ComposeInfo<S>, reply: Reply) -> ComposeState<S> {
|
||||
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 {
|
||||
fut,
|
||||
|
29
src/scope.rs
29
src/scope.rs
@ -274,7 +274,7 @@ impl<S: 'static> Scope<S> {
|
||||
}
|
||||
|
||||
impl<S: 'static> RouteHandler<S> for Scope<S> {
|
||||
fn handle(&mut self, mut req: HttpRequest<S>) -> Reply {
|
||||
fn handle(&mut self, mut req: HttpRequest<S>) -> Reply<HttpResponse> {
|
||||
let path = unsafe { &*(&req.match_info()["tail"] as *const _) };
|
||||
let path = if path == "" { "/" } else { path };
|
||||
|
||||
@ -346,7 +346,7 @@ struct Wrapper<S: 'static> {
|
||||
}
|
||||
|
||||
impl<S: 'static, S2: 'static> RouteHandler<S2> for Wrapper<S> {
|
||||
fn handle(&mut self, req: HttpRequest<S2>) -> Reply {
|
||||
fn handle(&mut self, req: HttpRequest<S2>) -> Reply<HttpResponse> {
|
||||
self.scope
|
||||
.handle(req.change_state(Rc::clone(&self.state)))
|
||||
}
|
||||
@ -521,9 +521,10 @@ struct WaitingResponse<S> {
|
||||
|
||||
impl<S: 'static> WaitingResponse<S> {
|
||||
#[inline]
|
||||
fn init(info: &mut ComposeInfo<S>, reply: Reply) -> ComposeState<S> {
|
||||
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 {
|
||||
fut,
|
||||
_s: PhantomData,
|
||||
@ -707,7 +708,7 @@ mod tests {
|
||||
|
||||
let req = TestRequest::with_uri("/app/path1").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::OK);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -724,10 +725,7 @@ mod tests {
|
||||
|
||||
let req = TestRequest::with_uri("/app/t1/path1").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::CREATED
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::CREATED);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -742,10 +740,7 @@ mod tests {
|
||||
|
||||
let req = TestRequest::with_uri("/app/t1/path1").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::CREATED
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::CREATED);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -760,16 +755,10 @@ mod tests {
|
||||
|
||||
let req = TestRequest::with_uri("/app/path2").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::BAD_REQUEST
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::BAD_REQUEST);
|
||||
|
||||
let req = TestRequest::with_uri("/path2").finish();
|
||||
let resp = app.run(req);
|
||||
assert_eq!(
|
||||
resp.as_response().unwrap().status(),
|
||||
StatusCode::NOT_FOUND
|
||||
);
|
||||
assert_eq!(resp.as_msg().status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
@ -602,6 +602,7 @@ 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."),
|
||||
},
|
||||
Err(err) => Err(err),
|
||||
|
253
src/with.rs
253
src/with.rs
@ -82,7 +82,7 @@ where
|
||||
T: FromRequest<S> + 'static,
|
||||
S: 'static,
|
||||
{
|
||||
type Result = Reply;
|
||||
type Result = Reply<HttpResponse>;
|
||||
|
||||
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result {
|
||||
let mut fut = WithHandlerFut {
|
||||
@ -97,7 +97,7 @@ where
|
||||
match fut.poll() {
|
||||
Ok(Async::Ready(resp)) => Reply::response(resp),
|
||||
Ok(Async::NotReady) => Reply::async(fut),
|
||||
Err(e) => Reply::response(e),
|
||||
Err(e) => Reply::error::<Error>(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -134,14 +134,14 @@ where
|
||||
|
||||
let item = if !self.started {
|
||||
self.started = true;
|
||||
let mut fut = T::from_request(&self.req, self.cfg.as_ref());
|
||||
match fut.poll() {
|
||||
Ok(Async::Ready(item)) => item,
|
||||
Ok(Async::NotReady) => {
|
||||
self.fut1 = Some(Box::new(fut));
|
||||
return Ok(Async::NotReady);
|
||||
let reply = T::from_request(&mut self.req, self.cfg.as_ref()).into();
|
||||
match reply.into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(msg) => msg,
|
||||
ReplyItem::Future(fut) => {
|
||||
self.fut1 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
} else {
|
||||
match self.fut1.as_mut().unwrap().poll()? {
|
||||
@ -157,6 +157,7 @@ where
|
||||
};
|
||||
|
||||
match item.into() {
|
||||
ReplyItem::Error(err) => Err(err),
|
||||
ReplyItem::Message(resp) => Ok(Async::Ready(resp)),
|
||||
ReplyItem::Future(fut) => {
|
||||
self.fut2 = Some(fut);
|
||||
@ -206,7 +207,7 @@ where
|
||||
T2: FromRequest<S> + 'static,
|
||||
S: 'static,
|
||||
{
|
||||
type Result = Reply;
|
||||
type Result = Reply<HttpResponse>;
|
||||
|
||||
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result {
|
||||
let mut fut = WithHandlerFut2 {
|
||||
@ -265,19 +266,32 @@ where
|
||||
|
||||
if !self.started {
|
||||
self.started = true;
|
||||
let mut fut = T1::from_request(&self.req, self.cfg1.as_ref());
|
||||
match fut.poll() {
|
||||
Ok(Async::Ready(item1)) => {
|
||||
let mut fut = T2::from_request(&self.req, self.cfg2.as_ref());
|
||||
match fut.poll() {
|
||||
Ok(Async::Ready(item2)) => {
|
||||
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::Message(resp) => {
|
||||
return Ok(Async::Ready(resp))
|
||||
let reply = T1::from_request(&mut 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) => {
|
||||
self.fut1 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
};
|
||||
|
||||
let reply = T2::from_request(&mut 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) => {
|
||||
self.item = Some(item1);
|
||||
self.fut2 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
};
|
||||
|
||||
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) => {
|
||||
self.fut3 = Some(fut);
|
||||
return self.poll();
|
||||
@ -286,31 +300,34 @@ where
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
}
|
||||
Ok(Async::NotReady) => {
|
||||
self.item = Some(item1);
|
||||
self.fut2 = Some(Box::new(fut));
|
||||
return Ok(Async::NotReady);
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
Ok(Async::NotReady) => {
|
||||
self.fut1 = Some(Box::new(fut));
|
||||
return Ok(Async::NotReady);
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
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 item2 = match reply.into() {
|
||||
ReplyItem::Error(err) => return Err(err),
|
||||
ReplyItem::Message(msg) => msg,
|
||||
ReplyItem::Future(fut) => {
|
||||
self.item = Some(item);
|
||||
self.fut1.take();
|
||||
self.fut2 = Some(Box::new(T2::from_request(
|
||||
&self.req,
|
||||
self.cfg2.as_ref(),
|
||||
)));
|
||||
self.fut2 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
};
|
||||
|
||||
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) => {
|
||||
self.fut3 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
},
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
}
|
||||
Async::NotReady => return Ok(Async::NotReady),
|
||||
}
|
||||
@ -330,6 +347,7 @@ 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),
|
||||
}
|
||||
@ -387,7 +405,7 @@ where
|
||||
T3: 'static,
|
||||
S: 'static,
|
||||
{
|
||||
type Result = Reply;
|
||||
type Result = Reply<HttpResponse>;
|
||||
|
||||
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result {
|
||||
let mut fut = WithHandlerFut3 {
|
||||
@ -454,24 +472,44 @@ where
|
||||
|
||||
if !self.started {
|
||||
self.started = true;
|
||||
let mut fut = T1::from_request(&self.req, self.cfg1.as_ref());
|
||||
match fut.poll() {
|
||||
Ok(Async::Ready(item1)) => {
|
||||
let mut fut = T2::from_request(&self.req, self.cfg2.as_ref());
|
||||
match fut.poll() {
|
||||
Ok(Async::Ready(item2)) => {
|
||||
let mut fut =
|
||||
T3::from_request(&self.req, self.cfg3.as_ref());
|
||||
match fut.poll() {
|
||||
Ok(Async::Ready(item3)) => {
|
||||
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::Message(resp) => {
|
||||
return Ok(Async::Ready(resp))
|
||||
let reply = T1::from_request(&mut 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) => {
|
||||
self.fut1 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
};
|
||||
|
||||
let reply = T2::from_request(&mut 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) => {
|
||||
self.item1 = Some(item1);
|
||||
self.fut2 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
};
|
||||
|
||||
let reply = T3::from_request(&mut 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) => {
|
||||
self.item1 = Some(item1);
|
||||
self.item2 = Some(item2);
|
||||
self.fut3 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
};
|
||||
|
||||
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) => {
|
||||
self.fut4 = Some(fut);
|
||||
return self.poll();
|
||||
@ -480,40 +518,48 @@ where
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
}
|
||||
Ok(Async::NotReady) => {
|
||||
self.item1 = Some(item1);
|
||||
self.item2 = Some(item2);
|
||||
self.fut3 = Some(Box::new(fut));
|
||||
return Ok(Async::NotReady);
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
Ok(Async::NotReady) => {
|
||||
self.item1 = Some(item1);
|
||||
self.fut2 = Some(Box::new(fut));
|
||||
return Ok(Async::NotReady);
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
Ok(Async::NotReady) => {
|
||||
self.fut1 = Some(Box::new(fut));
|
||||
return Ok(Async::NotReady);
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
if self.fut1.is_some() {
|
||||
match self.fut1.as_mut().unwrap().poll()? {
|
||||
Async::Ready(item) => {
|
||||
self.item1 = Some(item);
|
||||
self.fut1.take();
|
||||
self.fut2 = Some(Box::new(T2::from_request(
|
||||
&self.req,
|
||||
self.cfg2.as_ref(),
|
||||
)));
|
||||
let reply =
|
||||
T2::from_request(&mut 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) => {
|
||||
self.fut2 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
};
|
||||
|
||||
let reply =
|
||||
T3::from_request(&mut 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) => {
|
||||
self.item2 = Some(item2);
|
||||
self.fut3 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
};
|
||||
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) => {
|
||||
self.fut4 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
},
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
}
|
||||
Async::NotReady => return Ok(Async::NotReady),
|
||||
}
|
||||
@ -522,12 +568,32 @@ where
|
||||
if self.fut2.is_some() {
|
||||
match self.fut2.as_mut().unwrap().poll()? {
|
||||
Async::Ready(item) => {
|
||||
self.item2 = Some(item);
|
||||
self.fut2.take();
|
||||
self.fut3 = Some(Box::new(T3::from_request(
|
||||
&self.req,
|
||||
self.cfg3.as_ref(),
|
||||
)));
|
||||
let reply =
|
||||
T3::from_request(&mut 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) => {
|
||||
self.item2 = Some(item);
|
||||
self.fut3 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
};
|
||||
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) => {
|
||||
self.fut4 = Some(fut);
|
||||
return self.poll();
|
||||
}
|
||||
},
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
}
|
||||
Async::NotReady => return Ok(Async::NotReady),
|
||||
}
|
||||
@ -550,6 +616,7 @@ 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),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user