1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-28 01:32:57 +01:00

refactor Responder trait

This commit is contained in:
Nikolay Kim 2018-05-04 11:44:22 -07:00
parent 8b43574bd5
commit f37880d89c
8 changed files with 63 additions and 55 deletions

View File

@ -257,8 +257,8 @@ impl Responder for Binary {
type Item = HttpResponse; type Item = HttpResponse;
type Error = Error; type Error = Error;
fn respond_to(self, _: HttpRequest) -> Result<HttpResponse, Error> { fn respond_to<S>(self, req: &HttpRequest<S>) -> Result<HttpResponse, Error> {
Ok(HttpResponse::Ok() Ok(HttpResponse::build_from(req)
.content_type("application/octet-stream") .content_type("application/octet-stream")
.body(self)) .body(self))
} }

View File

@ -642,7 +642,7 @@ where
type Item = HttpResponse; type Item = HttpResponse;
type Error = Error; type Error = Error;
fn respond_to(self, _: HttpRequest) -> Result<HttpResponse, Error> { fn respond_to<S>(self, _: &HttpRequest<S>) -> Result<HttpResponse, Error> {
Err(self.into()) Err(self.into())
} }
} }

View File

@ -161,7 +161,7 @@ impl DerefMut for NamedFile {
} }
/// Returns true if `req` has no `If-Match` header or one which matches `etag`. /// Returns true if `req` has no `If-Match` header or one which matches `etag`.
fn any_match(etag: Option<&header::EntityTag>, req: &HttpRequest) -> bool { fn any_match<S>(etag: Option<&header::EntityTag>, req: &HttpRequest<S>) -> bool {
match req.get_header::<header::IfMatch>() { match req.get_header::<header::IfMatch>() {
None | Some(header::IfMatch::Any) => true, None | Some(header::IfMatch::Any) => true,
Some(header::IfMatch::Items(ref items)) => { Some(header::IfMatch::Items(ref items)) => {
@ -178,7 +178,7 @@ fn any_match(etag: Option<&header::EntityTag>, req: &HttpRequest) -> bool {
} }
/// Returns true if `req` doesn't have an `If-None-Match` header matching `req`. /// Returns true if `req` doesn't have an `If-None-Match` header matching `req`.
fn none_match(etag: Option<&header::EntityTag>, req: &HttpRequest) -> bool { fn none_match<S>(etag: Option<&header::EntityTag>, req: &HttpRequest<S>) -> bool {
match req.get_header::<header::IfNoneMatch>() { match req.get_header::<header::IfNoneMatch>() {
Some(header::IfNoneMatch::Any) => false, Some(header::IfNoneMatch::Any) => false,
Some(header::IfNoneMatch::Items(ref items)) => { Some(header::IfNoneMatch::Items(ref items)) => {
@ -199,7 +199,7 @@ impl Responder for NamedFile {
type Item = HttpResponse; type Item = HttpResponse;
type Error = io::Error; type Error = io::Error;
fn respond_to(self, req: HttpRequest) -> Result<HttpResponse, io::Error> { fn respond_to<S>(self, req: &HttpRequest<S>) -> Result<HttpResponse, io::Error> {
if self.status_code != StatusCode::OK { if self.status_code != StatusCode::OK {
let mut resp = HttpResponse::build(self.status_code); let mut resp = HttpResponse::build(self.status_code);
resp.if_some(self.path().extension(), |ext, resp| { resp.if_some(self.path().extension(), |ext, resp| {
@ -244,7 +244,7 @@ impl Responder for NamedFile {
let last_modified = self.last_modified(); let last_modified = self.last_modified();
// check preconditions // check preconditions
let precondition_failed = if !any_match(etag.as_ref(), &req) { let precondition_failed = if !any_match(etag.as_ref(), req) {
true true
} else if let (Some(ref m), Some(header::IfUnmodifiedSince(ref since))) = } else if let (Some(ref m), Some(header::IfUnmodifiedSince(ref since))) =
(last_modified, req.get_header()) (last_modified, req.get_header())
@ -255,7 +255,7 @@ impl Responder for NamedFile {
}; };
// check last modified // check last modified
let not_modified = if !none_match(etag.as_ref(), &req) { let not_modified = if !none_match(etag.as_ref(), req) {
true true
} else if let (Some(ref m), Some(header::IfModifiedSince(ref since))) = } else if let (Some(ref m), Some(header::IfModifiedSince(ref since))) =
(last_modified, req.get_header()) (last_modified, req.get_header())
@ -612,7 +612,7 @@ impl<S: 'static> Handler<S> for StaticFiles<S> {
HttpResponse::Found() HttpResponse::Found()
.header(header::LOCATION, new_path.as_str()) .header(header::LOCATION, new_path.as_str())
.finish() .finish()
.respond_to(req.drop_state()) .respond_to(&req)
} else if self.show_index { } else if self.show_index {
let dir = Directory::new(self.directory.clone(), path); let dir = Directory::new(self.directory.clone(), path);
Ok((*self.renderer)(&dir, &req)?.into()) Ok((*self.renderer)(&dir, &req)?.into())
@ -622,8 +622,8 @@ impl<S: 'static> Handler<S> for StaticFiles<S> {
} else { } else {
NamedFile::open(path)? NamedFile::open(path)?
.set_cpu_pool(self.cpu_pool.clone()) .set_cpu_pool(self.cpu_pool.clone())
.respond_to(req.drop_state())? .respond_to(&req)?
.respond_to(req.drop_state()) .respond_to(&req)
} }
} }
} }

View File

@ -29,7 +29,9 @@ pub trait Responder {
type Error: Into<Error>; type Error: Into<Error>;
/// Convert itself to `AsyncResult` or `Error`. /// Convert itself to `AsyncResult` or `Error`.
fn respond_to(self, req: HttpRequest) -> Result<Self::Item, Self::Error>; fn respond_to<S: 'static>(
self, req: &HttpRequest<S>,
) -> Result<Self::Item, Self::Error>;
} }
/// Trait implemented by types that can be extracted from request. /// Trait implemented by types that can be extracted from request.
@ -96,7 +98,9 @@ where
type Item = AsyncResult<HttpResponse>; type Item = AsyncResult<HttpResponse>;
type Error = Error; type Error = Error;
fn respond_to(self, req: HttpRequest) -> Result<AsyncResult<HttpResponse>, Error> { fn respond_to<S: 'static>(
self, req: &HttpRequest<S>,
) -> Result<AsyncResult<HttpResponse>, Error> {
match self { match self {
Either::A(a) => match a.respond_to(req) { Either::A(a) => match a.respond_to(req) {
Ok(val) => Ok(val.into()), Ok(val) => Ok(val.into()),
@ -232,7 +236,7 @@ impl<I, E> AsyncResult<I, E> {
/// Send error /// Send error
#[inline] #[inline]
pub fn error<R: Into<E>>(err: R) -> AsyncResult<I, E> { pub fn err<R: Into<E>>(err: R) -> AsyncResult<I, E> {
AsyncResult(Some(AsyncResultItem::Err(err.into()))) AsyncResult(Some(AsyncResultItem::Err(err.into())))
} }
@ -262,7 +266,9 @@ impl Responder for AsyncResult<HttpResponse> {
type Item = AsyncResult<HttpResponse>; type Item = AsyncResult<HttpResponse>;
type Error = Error; type Error = Error;
fn respond_to(self, _: HttpRequest) -> Result<AsyncResult<HttpResponse>, Error> { fn respond_to<S>(
self, _: &HttpRequest<S>,
) -> Result<AsyncResult<HttpResponse>, Error> {
Ok(self) Ok(self)
} }
} }
@ -272,7 +278,9 @@ impl Responder for HttpResponse {
type Error = Error; type Error = Error;
#[inline] #[inline]
fn respond_to(self, _: HttpRequest) -> Result<AsyncResult<HttpResponse>, Error> { fn respond_to<S>(
self, _: &HttpRequest<S>,
) -> Result<AsyncResult<HttpResponse>, Error> {
Ok(AsyncResult(Some(AsyncResultItem::Ok(self)))) Ok(AsyncResult(Some(AsyncResultItem::Ok(self))))
} }
} }
@ -288,7 +296,7 @@ impl<T: Responder, E: Into<Error>> Responder for Result<T, E> {
type Item = <T as Responder>::Item; type Item = <T as Responder>::Item;
type Error = Error; type Error = Error;
fn respond_to(self, req: HttpRequest) -> Result<Self::Item, Self::Error> { fn respond_to<S: 'static>(self, req: &HttpRequest<S>) -> Result<Self::Item, Error> {
match self { match self {
Ok(val) => match val.respond_to(req) { Ok(val) => match val.respond_to(req) {
Ok(val) => Ok(val), Ok(val) => Ok(val),
@ -350,9 +358,12 @@ where
type Error = Error; type Error = Error;
#[inline] #[inline]
fn respond_to(self, req: HttpRequest) -> Result<AsyncResult<HttpResponse>, Error> { fn respond_to<S: 'static>(
self, req: &HttpRequest<S>,
) -> Result<AsyncResult<HttpResponse>, Error> {
let req = req.clone();
let fut = self.map_err(|e| e.into()) let fut = self.map_err(|e| e.into())
.then(move |r| match r.respond_to(req) { .then(move |r| match r.respond_to(&req) {
Ok(reply) => match reply.into().into() { Ok(reply) => match reply.into().into() {
AsyncResultItem::Ok(resp) => ok(resp), AsyncResultItem::Ok(resp) => ok(resp),
_ => panic!("Nested async replies are not supported"), _ => panic!("Nested async replies are not supported"),
@ -363,7 +374,7 @@ where
} }
} }
/// Trait defines object that could be registered as resource route // /// Trait defines object that could be registered as resource route
pub(crate) trait RouteHandler<S>: 'static { pub(crate) trait RouteHandler<S>: 'static {
fn handle(&mut self, req: HttpRequest<S>) -> AsyncResult<HttpResponse>; fn handle(&mut self, req: HttpRequest<S>) -> AsyncResult<HttpResponse>;
} }
@ -400,10 +411,9 @@ where
S: 'static, S: 'static,
{ {
fn handle(&mut self, req: HttpRequest<S>) -> AsyncResult<HttpResponse> { fn handle(&mut self, req: HttpRequest<S>) -> AsyncResult<HttpResponse> {
let req2 = req.drop_state(); match self.h.handle(req.clone()).respond_to(&req) {
match self.h.handle(req).respond_to(req2) {
Ok(reply) => reply.into(), Ok(reply) => reply.into(),
Err(err) => AsyncResult::ok(err.into()), Err(err) => AsyncResult::err(err.into()),
} }
} }
} }
@ -446,16 +456,16 @@ where
S: 'static, S: 'static,
{ {
fn handle(&mut self, req: HttpRequest<S>) -> AsyncResult<HttpResponse> { fn handle(&mut self, req: HttpRequest<S>) -> AsyncResult<HttpResponse> {
let req2 = req.drop_state(); let fut = (self.h)(req.clone())
let fut = (self.h)(req).map_err(|e| e.into()).then(move |r| { .map_err(|e| e.into())
match r.respond_to(req2) { .then(move |r| match r.respond_to(&req) {
Ok(reply) => match reply.into().into() { Ok(reply) => match reply.into().into() {
AsyncResultItem::Ok(resp) => ok(resp), AsyncResultItem::Ok(resp) => Either::A(ok(resp)),
_ => panic!("Nested async replies are not supported"), AsyncResultItem::Err(e) => Either::A(err(e)),
AsyncResultItem::Future(fut) => Either::B(fut),
}, },
Err(e) => err(e), Err(e) => Either::A(err(e)),
} });
});
AsyncResult::async(Box::new(fut)) AsyncResult::async(Box::new(fut))
} }
} }

View File

@ -636,7 +636,7 @@ impl Responder for HttpResponseBuilder {
type Error = Error; type Error = Error;
#[inline] #[inline]
fn respond_to(mut self, _: HttpRequest) -> Result<HttpResponse, Error> { fn respond_to<S>(mut self, _: &HttpRequest<S>) -> Result<HttpResponse, Error> {
Ok(self.finish()) Ok(self.finish())
} }
} }
@ -653,7 +653,7 @@ impl Responder for &'static str {
type Item = HttpResponse; type Item = HttpResponse;
type Error = Error; type Error = Error;
fn respond_to(self, req: HttpRequest) -> Result<HttpResponse, Error> { fn respond_to<S>(self, req: &HttpRequest<S>) -> Result<HttpResponse, Error> {
Ok(req.build_response(StatusCode::OK) Ok(req.build_response(StatusCode::OK)
.content_type("text/plain; charset=utf-8") .content_type("text/plain; charset=utf-8")
.body(self)) .body(self))
@ -672,7 +672,7 @@ impl Responder for &'static [u8] {
type Item = HttpResponse; type Item = HttpResponse;
type Error = Error; type Error = Error;
fn respond_to(self, req: HttpRequest) -> Result<HttpResponse, Error> { fn respond_to<S>(self, req: &HttpRequest<S>) -> Result<HttpResponse, Error> {
Ok(req.build_response(StatusCode::OK) Ok(req.build_response(StatusCode::OK)
.content_type("application/octet-stream") .content_type("application/octet-stream")
.body(self)) .body(self))
@ -691,7 +691,7 @@ impl Responder for String {
type Item = HttpResponse; type Item = HttpResponse;
type Error = Error; type Error = Error;
fn respond_to(self, req: HttpRequest) -> Result<HttpResponse, Error> { fn respond_to<S>(self, req: &HttpRequest<S>) -> Result<HttpResponse, Error> {
Ok(req.build_response(StatusCode::OK) Ok(req.build_response(StatusCode::OK)
.content_type("text/plain; charset=utf-8") .content_type("text/plain; charset=utf-8")
.body(self)) .body(self))
@ -710,7 +710,7 @@ impl<'a> Responder for &'a String {
type Item = HttpResponse; type Item = HttpResponse;
type Error = Error; type Error = Error;
fn respond_to(self, req: HttpRequest) -> Result<HttpResponse, Error> { fn respond_to<S>(self, req: &HttpRequest<S>) -> Result<HttpResponse, Error> {
Ok(req.build_response(StatusCode::OK) Ok(req.build_response(StatusCode::OK)
.content_type("text/plain; charset=utf-8") .content_type("text/plain; charset=utf-8")
.body(self)) .body(self))
@ -729,7 +729,7 @@ impl Responder for Bytes {
type Item = HttpResponse; type Item = HttpResponse;
type Error = Error; type Error = Error;
fn respond_to(self, req: HttpRequest) -> Result<HttpResponse, Error> { fn respond_to<S>(self, req: &HttpRequest<S>) -> Result<HttpResponse, Error> {
Ok(req.build_response(StatusCode::OK) Ok(req.build_response(StatusCode::OK)
.content_type("application/octet-stream") .content_type("application/octet-stream")
.body(self)) .body(self))
@ -748,7 +748,7 @@ impl Responder for BytesMut {
type Item = HttpResponse; type Item = HttpResponse;
type Error = Error; type Error = Error;
fn respond_to(self, req: HttpRequest) -> Result<HttpResponse, Error> { fn respond_to<S>(self, req: &HttpRequest<S>) -> Result<HttpResponse, Error> {
Ok(req.build_response(StatusCode::OK) Ok(req.build_response(StatusCode::OK)
.content_type("application/octet-stream") .content_type("application/octet-stream")
.body(self)) .body(self))

View File

@ -118,7 +118,7 @@ impl<T: Serialize> Responder for Json<T> {
type Item = HttpResponse; type Item = HttpResponse;
type Error = Error; type Error = Error;
fn respond_to(self, req: HttpRequest) -> Result<HttpResponse, Error> { fn respond_to<S>(self, req: &HttpRequest<S>) -> Result<HttpResponse, Error> {
let body = serde_json::to_string(&self.0)?; let body = serde_json::to_string(&self.0)?;
Ok(req.build_response(StatusCode::OK) Ok(req.build_response(StatusCode::OK)
@ -351,7 +351,7 @@ mod tests {
let json = Json(MyObject { let json = Json(MyObject {
name: "test".to_owned(), name: "test".to_owned(),
}); });
let resp = json.respond_to(HttpRequest::default()).unwrap(); let resp = json.respond_to(&HttpRequest::default()).unwrap();
assert_eq!( assert_eq!(
resp.headers().get(header::CONTENT_TYPE).unwrap(), resp.headers().get(header::CONTENT_TYPE).unwrap(),
"application/json" "application/json"

View File

@ -478,7 +478,7 @@ impl TestRequest<()> {
} }
} }
impl<S> TestRequest<S> { impl<S: 'static> TestRequest<S> {
/// Start HttpRequest build process with application state /// Start HttpRequest build process with application state
pub fn with_state(state: S) -> TestRequest<S> { pub fn with_state(state: S) -> TestRequest<S> {
TestRequest { TestRequest {
@ -597,7 +597,7 @@ impl<S> TestRequest<S> {
let req = self.finish(); let req = self.finish();
let resp = h.handle(req.clone()); let resp = h.handle(req.clone());
match resp.respond_to(req.drop_state()) { match resp.respond_to(&req) {
Ok(resp) => match resp.into().into() { Ok(resp) => match resp.into().into() {
AsyncResultItem::Ok(resp) => Ok(resp), AsyncResultItem::Ok(resp) => Ok(resp),
AsyncResultItem::Err(err) => Err(err), AsyncResultItem::Err(err) => Err(err),
@ -623,7 +623,7 @@ impl<S> TestRequest<S> {
let mut core = Core::new().unwrap(); let mut core = Core::new().unwrap();
match core.run(fut) { match core.run(fut) {
Ok(r) => match r.respond_to(req.drop_state()) { Ok(r) => match r.respond_to(&req) {
Ok(reply) => match reply.into().into() { Ok(reply) => match reply.into().into() {
AsyncResultItem::Ok(resp) => Ok(resp), AsyncResultItem::Ok(resp) => Ok(resp),
_ => panic!("Nested async replies are not supported"), _ => panic!("Nested async replies are not supported"),

View File

@ -97,7 +97,7 @@ where
match fut.poll() { match fut.poll() {
Ok(Async::Ready(resp)) => AsyncResult::ok(resp), Ok(Async::Ready(resp)) => AsyncResult::ok(resp),
Ok(Async::NotReady) => AsyncResult::async(Box::new(fut)), Ok(Async::NotReady) => AsyncResult::async(Box::new(fut)),
Err(e) => AsyncResult::error::<Error>(e), Err(e) => AsyncResult::err(e),
} }
} }
} }
@ -151,7 +151,7 @@ where
}; };
let hnd: &mut F = unsafe { &mut *self.hnd.get() }; let hnd: &mut F = unsafe { &mut *self.hnd.get() };
let item = match (*hnd)(item).respond_to(self.req.drop_state()) { let item = match (*hnd)(item).respond_to(&self.req) {
Ok(item) => item.into(), Ok(item) => item.into(),
Err(e) => return Err(e.into()), Err(e) => return Err(e.into()),
}; };
@ -288,7 +288,7 @@ where
}; };
let hnd: &mut F = unsafe { &mut *self.hnd.get() }; let hnd: &mut F = unsafe { &mut *self.hnd.get() };
match (*hnd)(item1, item2).respond_to(self.req.drop_state()) { match (*hnd)(item1, item2).respond_to(&self.req) {
Ok(item) => match item.into().into() { Ok(item) => match item.into().into() {
AsyncResultItem::Err(err) => return Err(err), AsyncResultItem::Err(err) => return Err(err),
AsyncResultItem::Ok(resp) => return Ok(Async::Ready(resp)), AsyncResultItem::Ok(resp) => return Ok(Async::Ready(resp)),
@ -316,7 +316,7 @@ where
}; };
let hnd: &mut F = unsafe { &mut *self.hnd.get() }; let hnd: &mut F = unsafe { &mut *self.hnd.get() };
match (*hnd)(item, item2).respond_to(self.req.drop_state()) { match (*hnd)(item, item2).respond_to(&self.req) {
Ok(item) => match item.into().into() { Ok(item) => match item.into().into() {
AsyncResultItem::Err(err) => return Err(err), AsyncResultItem::Err(err) => return Err(err),
AsyncResultItem::Ok(resp) => return Ok(Async::Ready(resp)), AsyncResultItem::Ok(resp) => return Ok(Async::Ready(resp)),
@ -338,9 +338,7 @@ where
}; };
let hnd: &mut F = unsafe { &mut *self.hnd.get() }; let hnd: &mut F = unsafe { &mut *self.hnd.get() };
let item = match (*hnd)(self.item.take().unwrap(), item) let item = match (*hnd)(self.item.take().unwrap(), item).respond_to(&self.req) {
.respond_to(self.req.drop_state())
{
Ok(item) => item.into(), Ok(item) => item.into(),
Err(err) => return Err(err.into()), Err(err) => return Err(err.into()),
}; };
@ -424,7 +422,7 @@ where
match fut.poll() { match fut.poll() {
Ok(Async::Ready(resp)) => AsyncResult::ok(resp), Ok(Async::Ready(resp)) => AsyncResult::ok(resp),
Ok(Async::NotReady) => AsyncResult::async(Box::new(fut)), Ok(Async::NotReady) => AsyncResult::async(Box::new(fut)),
Err(e) => AsyncResult::error(e), Err(e) => AsyncResult::err(e),
} }
} }
} }
@ -505,7 +503,7 @@ where
}; };
let hnd: &mut F = unsafe { &mut *self.hnd.get() }; let hnd: &mut F = unsafe { &mut *self.hnd.get() };
match (*hnd)(item1, item2, item3).respond_to(self.req.drop_state()) { match (*hnd)(item1, item2, item3).respond_to(&self.req) {
Ok(item) => match item.into().into() { Ok(item) => match item.into().into() {
AsyncResultItem::Err(err) => return Err(err), AsyncResultItem::Err(err) => return Err(err),
AsyncResultItem::Ok(resp) => return Ok(Async::Ready(resp)), AsyncResultItem::Ok(resp) => return Ok(Async::Ready(resp)),
@ -545,7 +543,7 @@ where
}; };
let hnd: &mut F = unsafe { &mut *self.hnd.get() }; let hnd: &mut F = unsafe { &mut *self.hnd.get() };
match (*hnd)(self.item1.take().unwrap(), item2, item3) match (*hnd)(self.item1.take().unwrap(), item2, item3)
.respond_to(self.req.drop_state()) .respond_to(&self.req)
{ {
Ok(item) => match item.into().into() { Ok(item) => match item.into().into() {
AsyncResultItem::Err(err) => return Err(err), AsyncResultItem::Err(err) => return Err(err),
@ -578,7 +576,7 @@ where
}; };
let hnd: &mut F = unsafe { &mut *self.hnd.get() }; let hnd: &mut F = unsafe { &mut *self.hnd.get() };
match (*hnd)(self.item1.take().unwrap(), item, item3) match (*hnd)(self.item1.take().unwrap(), item, item3)
.respond_to(self.req.drop_state()) .respond_to(&self.req)
{ {
Ok(item) => match item.into().into() { Ok(item) => match item.into().into() {
AsyncResultItem::Err(err) => return Err(err), AsyncResultItem::Err(err) => return Err(err),
@ -605,7 +603,7 @@ where
self.item1.take().unwrap(), self.item1.take().unwrap(),
self.item2.take().unwrap(), self.item2.take().unwrap(),
item, item,
).respond_to(self.req.drop_state()) ).respond_to(&self.req)
{ {
Ok(item) => item.into(), Ok(item) => item.into(),
Err(err) => return Err(err.into()), Err(err) => return Err(err.into()),