From 1d01dbaaf947beb541424628d4c7cf9f5cea4542 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 13 Jun 2018 23:44:24 -0700 Subject: [PATCH] make Responder trait generic over S --- CHANGES.md | 6 +++-- MIGRATION.md | 3 +++ src/application.rs | 4 +-- src/body.rs | 4 +-- src/error.rs | 4 +-- src/fs.rs | 66 +++++++++++++++++++++++---------------------- src/handler.rs | 62 +++++++++++++++++++----------------------- src/httpresponse.rs | 28 +++++++++---------- src/json.rs | 4 +-- src/lib.rs | 2 +- src/resource.rs | 8 +++--- src/route.rs | 10 +++---- src/scope.rs | 2 +- src/test.rs | 2 +- src/with.rs | 16 +++++------ 15 files changed, 111 insertions(+), 110 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5265d9d79..d2e74f41e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -28,11 +28,13 @@ * Min rustc version is 1.26 +* Use tokio instead of tokio-core + +* `Responder` trait refactored. It is generic over `S` + * `HttpResponse::into_builder()` now moves cookies into the builder instead of dropping them -* Use tokio instead of tokio-core - * Use `&mut self` instead of `&self` for Middleware trait * Added header `User-Agent: Actix-web/` to default headers when building a request diff --git a/MIGRATION.md b/MIGRATION.md index 628f0590e..c4e9cdc32 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -24,6 +24,9 @@ } ``` +* `Responder` trait is changed. It is generic over `S` - `Responder`. + `Responder::respond_to()` is not generic. + * [Middleware](https://actix.rs/actix-web/actix_web/middleware/trait.Middleware.html) trait uses `&mut self` instead of `&self`. diff --git a/src/application.rs b/src/application.rs index b9fa3e328..3ce3675dd 100644 --- a/src/application.rs +++ b/src/application.rs @@ -345,7 +345,7 @@ where pub fn route(mut self, path: &str, method: Method, f: F) -> App where F: Fn(T) -> R + 'static, - R: Responder + 'static, + R: Responder + 'static, T: FromRequest + 'static, { { @@ -737,7 +737,7 @@ impl Iterator for App { #[cfg(test)] mod tests { use super::*; - use body::{Body, Binary}; + use body::{Binary, Body}; use http::StatusCode; use httprequest::HttpRequest; use httpresponse::HttpResponse; diff --git a/src/body.rs b/src/body.rs index a93db1e92..e6d39990f 100644 --- a/src/body.rs +++ b/src/body.rs @@ -254,11 +254,11 @@ impl AsRef<[u8]> for Binary { } } -impl Responder for Binary { +impl Responder for Binary { type Item = HttpResponse; type Error = Error; - fn respond_to(self, req: &HttpRequest) -> Result { + fn respond_to(self, req: &HttpRequest) -> Result { Ok(HttpResponse::build_from(req) .content_type("application/octet-stream") .body(self)) diff --git a/src/error.rs b/src/error.rs index bbafb1c41..a3b63c5f6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -743,14 +743,14 @@ where } } -impl Responder for InternalError +impl Responder for InternalError where T: Send + Sync + fmt::Debug + fmt::Display + 'static, { type Item = HttpResponse; type Error = Error; - fn respond_to(self, _: &HttpRequest) -> Result { + fn respond_to(self, _: &HttpRequest) -> Result { Err(self.into()) } } diff --git a/src/fs.rs b/src/fs.rs index 35c78b736..48d7f34b3 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -63,18 +63,20 @@ impl NamedFile { /// let file = NamedFile::open("foo.txt"); /// ``` pub fn open>(path: P) -> io::Result { - use header::{ContentDisposition, DispositionType, DispositionParam}; + use header::{ContentDisposition, DispositionParam, DispositionType}; let path = path.as_ref().to_path_buf(); // Get the name of the file and use it to construct default Content-Type // and Content-Disposition values - let (content_type, content_disposition) = - { + let (content_type, content_disposition) = { let filename = match path.file_name() { Some(name) => name.to_string_lossy(), - None => return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "Provided path has no filename")), + None => { + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "Provided path has no filename", + )) + } }; let ct = guess_mime_type(&path); @@ -84,13 +86,11 @@ impl NamedFile { }; let cd = ContentDisposition { disposition: disposition_type, - parameters: vec![ - DispositionParam::Filename( - header::Charset::Ext("UTF-8".to_owned()), - None, - filename.as_bytes().to_vec(), - ) - ], + parameters: vec![DispositionParam::Filename( + header::Charset::Ext("UTF-8".to_owned()), + None, + filename.as_bytes().to_vec(), + )], }; (ct, cd) }; @@ -268,15 +268,18 @@ fn none_match(etag: Option<&header::EntityTag>, req: &HttpRequest) -> bool } } -impl Responder for NamedFile { +impl Responder for NamedFile { type Item = HttpResponse; type Error = io::Error; - fn respond_to(self, req: &HttpRequest) -> Result { + fn respond_to(self, req: &HttpRequest) -> Result { if self.status_code != StatusCode::OK { let mut resp = HttpResponse::build(self.status_code); resp.set(header::ContentType(self.content_type.clone())) - .header(header::CONTENT_DISPOSITION, self.content_disposition.to_string()); + .header( + header::CONTENT_DISPOSITION, + self.content_disposition.to_string(), + ); if let Some(current_encoding) = self.encoding { resp.content_encoding(current_encoding); @@ -327,19 +330,20 @@ impl Responder for NamedFile { let mut resp = HttpResponse::build(self.status_code); resp.set(header::ContentType(self.content_type.clone())) - .header(header::CONTENT_DISPOSITION, self.content_disposition.to_string()); + .header( + header::CONTENT_DISPOSITION, + self.content_disposition.to_string(), + ); if let Some(current_encoding) = self.encoding { resp.content_encoding(current_encoding); } - resp - .if_some(last_modified, |lm, resp| { - resp.set(header::LastModified(lm)); - }) - .if_some(etag, |etag, resp| { - resp.set(header::ETag(etag)); - }); + resp.if_some(last_modified, |lm, resp| { + resp.set(header::LastModified(lm)); + }).if_some(etag, |etag, resp| { + resp.set(header::ETag(etag)); + }); resp.header(header::ACCEPT_RANGES, "bytes"); @@ -816,16 +820,14 @@ mod tests { #[test] fn test_named_file_image_attachment() { - use header::{ContentDisposition, DispositionType, DispositionParam}; + use header::{ContentDisposition, DispositionParam, DispositionType}; let cd = ContentDisposition { disposition: DispositionType::Attachment, - parameters: vec![ - DispositionParam::Filename( - header::Charset::Ext("UTF-8".to_owned()), - None, - "test.png".as_bytes().to_vec(), - ) - ], + parameters: vec![DispositionParam::Filename( + header::Charset::Ext("UTF-8".to_owned()), + None, + "test.png".as_bytes().to_vec(), + )], }; let mut file = NamedFile::open("tests/test.png") .unwrap() diff --git a/src/handler.rs b/src/handler.rs index d330e0716..c2611c429 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -13,7 +13,7 @@ use httpresponse::HttpResponse; #[allow(unused_variables)] pub trait Handler: 'static { /// The type of value that handler will return. - type Result: Responder; + type Result: Responder; /// Handle request fn handle(&mut self, req: HttpRequest) -> Self::Result; @@ -22,7 +22,7 @@ pub trait Handler: 'static { /// Trait implemented by types that generate responses for clients. /// /// Types that implement this trait can be used as the return type of a handler. -pub trait Responder { +pub trait Responder { /// The associated item which can be returned. type Item: Into>; @@ -30,9 +30,7 @@ pub trait Responder { type Error: Into; /// Convert itself to `AsyncResult` or `Error`. - fn respond_to( - self, req: &HttpRequest, - ) -> Result; + fn respond_to(self, req: &HttpRequest) -> Result; } /// Trait implemented by types that can be extracted from request. @@ -93,15 +91,15 @@ pub enum Either { B(B), } -impl Responder for Either +impl Responder for Either where - A: Responder, - B: Responder, + A: Responder, + B: Responder, { type Item = AsyncResult; type Error = Error; - fn respond_to( + fn respond_to( self, req: &HttpRequest, ) -> Result, Error> { match self { @@ -133,14 +131,14 @@ where } } -impl Responder for Option +impl Responder for Option where - T: Responder, + T: Responder, { type Item = AsyncResult; type Error = Error; - fn respond_to( + fn respond_to( self, req: &HttpRequest, ) -> Result, Error> { match self { @@ -190,7 +188,7 @@ pub trait AsyncResponder: Sized { impl AsyncResponder for F where F: Future + 'static, - I: Responder + 'static, + I: 'static, E: Into + 'static, { fn responder(self) -> Box> { @@ -202,7 +200,7 @@ where impl Handler for F where F: Fn(HttpRequest) -> R + 'static, - R: Responder + 'static, + R: Responder + 'static, { type Result = R; @@ -287,25 +285,21 @@ impl AsyncResult { } } -impl Responder for AsyncResult { +impl Responder for AsyncResult { type Item = AsyncResult; type Error = Error; - fn respond_to( - self, _: &HttpRequest, - ) -> Result, Error> { + fn respond_to(self, _: &HttpRequest) -> Result, Error> { Ok(self) } } -impl Responder for HttpResponse { +impl Responder for HttpResponse { type Item = AsyncResult; type Error = Error; #[inline] - fn respond_to( - self, _: &HttpRequest, - ) -> Result, Error> { + fn respond_to(self, _: &HttpRequest) -> Result, Error> { Ok(AsyncResult(Some(AsyncResultItem::Ok(self)))) } } @@ -317,11 +311,11 @@ impl From for AsyncResult { } } -impl> Responder for Result { - type Item = ::Item; +impl, E: Into> Responder for Result { + type Item = >::Item; type Error = Error; - fn respond_to(self, req: &HttpRequest) -> Result { + fn respond_to(self, req: &HttpRequest) -> Result { match self { Ok(val) => match val.respond_to(req) { Ok(val) => Ok(val), @@ -374,16 +368,16 @@ impl From>> for AsyncResult { /// Convenience type alias pub type FutureResponse = Box>; -impl Responder for Box> +impl Responder for Box> where - I: Responder + 'static, + I: Responder + 'static, E: Into + 'static, { type Item = AsyncResult; type Error = Error; #[inline] - fn respond_to( + fn respond_to( self, req: &HttpRequest, ) -> Result, Error> { let req = req.clone(); @@ -409,7 +403,7 @@ pub(crate) trait RouteHandler: 'static { pub(crate) struct WrapHandler where H: Handler, - R: Responder, + R: Responder, S: 'static, { h: H, @@ -419,7 +413,7 @@ where impl WrapHandler where H: Handler, - R: Responder, + R: Responder, S: 'static, { pub fn new(h: H) -> Self { @@ -430,7 +424,7 @@ where impl RouteHandler for WrapHandler where H: Handler, - R: Responder + 'static, + R: Responder + 'static, S: 'static, { fn handle(&mut self, req: HttpRequest) -> AsyncResult { @@ -446,7 +440,7 @@ pub(crate) struct AsyncHandler where H: Fn(HttpRequest) -> F + 'static, F: Future + 'static, - R: Responder + 'static, + R: Responder + 'static, E: Into + 'static, S: 'static, { @@ -458,7 +452,7 @@ impl AsyncHandler where H: Fn(HttpRequest) -> F + 'static, F: Future + 'static, - R: Responder + 'static, + R: Responder + 'static, E: Into + 'static, S: 'static, { @@ -474,7 +468,7 @@ impl RouteHandler for AsyncHandler where H: Fn(HttpRequest) -> F + 'static, F: Future + 'static, - R: Responder + 'static, + R: Responder + 'static, E: Into + 'static, S: 'static, { diff --git a/src/httpresponse.rs b/src/httpresponse.rs index a0eb46a6c..45e590054 100644 --- a/src/httpresponse.rs +++ b/src/httpresponse.rs @@ -723,12 +723,12 @@ impl From for HttpResponse { } } -impl Responder for HttpResponseBuilder { +impl Responder for HttpResponseBuilder { type Item = HttpResponse; type Error = Error; #[inline] - fn respond_to(mut self, _: &HttpRequest) -> Result { + fn respond_to(mut self, _: &HttpRequest) -> Result { Ok(self.finish()) } } @@ -741,11 +741,11 @@ impl From<&'static str> for HttpResponse { } } -impl Responder for &'static str { +impl Responder for &'static str { type Item = HttpResponse; type Error = Error; - fn respond_to(self, req: &HttpRequest) -> Result { + fn respond_to(self, req: &HttpRequest) -> Result { Ok(req .build_response(StatusCode::OK) .content_type("text/plain; charset=utf-8") @@ -761,11 +761,11 @@ impl From<&'static [u8]> for HttpResponse { } } -impl Responder for &'static [u8] { +impl Responder for &'static [u8] { type Item = HttpResponse; type Error = Error; - fn respond_to(self, req: &HttpRequest) -> Result { + fn respond_to(self, req: &HttpRequest) -> Result { Ok(req .build_response(StatusCode::OK) .content_type("application/octet-stream") @@ -781,11 +781,11 @@ impl From for HttpResponse { } } -impl Responder for String { +impl Responder for String { type Item = HttpResponse; type Error = Error; - fn respond_to(self, req: &HttpRequest) -> Result { + fn respond_to(self, req: &HttpRequest) -> Result { Ok(req .build_response(StatusCode::OK) .content_type("text/plain; charset=utf-8") @@ -801,11 +801,11 @@ impl<'a> From<&'a String> for HttpResponse { } } -impl<'a> Responder for &'a String { +impl<'a, S> Responder for &'a String { type Item = HttpResponse; type Error = Error; - fn respond_to(self, req: &HttpRequest) -> Result { + fn respond_to(self, req: &HttpRequest) -> Result { Ok(req .build_response(StatusCode::OK) .content_type("text/plain; charset=utf-8") @@ -821,11 +821,11 @@ impl From for HttpResponse { } } -impl Responder for Bytes { +impl Responder for Bytes { type Item = HttpResponse; type Error = Error; - fn respond_to(self, req: &HttpRequest) -> Result { + fn respond_to(self, req: &HttpRequest) -> Result { Ok(req .build_response(StatusCode::OK) .content_type("application/octet-stream") @@ -841,11 +841,11 @@ impl From for HttpResponse { } } -impl Responder for BytesMut { +impl Responder for BytesMut { type Item = HttpResponse; type Error = Error; - fn respond_to(self, req: &HttpRequest) -> Result { + fn respond_to(self, req: &HttpRequest) -> Result { Ok(req .build_response(StatusCode::OK) .content_type("application/octet-stream") diff --git a/src/json.rs b/src/json.rs index d0e12c04d..41186976f 100644 --- a/src/json.rs +++ b/src/json.rs @@ -116,11 +116,11 @@ where } } -impl Responder for Json { +impl Responder for Json { type Item = HttpResponse; type Error = Error; - fn respond_to(self, req: &HttpRequest) -> Result { + fn respond_to(self, req: &HttpRequest) -> Result { let body = serde_json::to_string(&self.0)?; Ok(req diff --git a/src/lib.rs b/src/lib.rs index c3b9fc7af..eeead5e12 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,7 @@ //! use actix_web::{server, App, Path, Responder}; //! # use std::thread; //! -//! fn index(info: Path<(String, u32)>) -> impl Responder { +//! fn index(info: Path<(String, u32)>) -> impl Responder<()> { //! format!("Hello {}! id:{}", info.0, info.1) //! } //! diff --git a/src/resource.rs b/src/resource.rs index 2b9c8538b..a206b04f0 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -1,6 +1,6 @@ +use std::cell::RefCell; use std::marker::PhantomData; use std::rc::Rc; -use std::cell::RefCell; use futures::Future; use http::{Method, StatusCode}; @@ -194,7 +194,7 @@ impl ResourceHandler { pub fn f(&mut self, handler: F) where F: Fn(HttpRequest) -> R + 'static, - R: Responder + 'static, + R: Responder + 'static, { self.routes.push(Route::default()); self.routes.last_mut().unwrap().f(handler) @@ -221,7 +221,7 @@ impl ResourceHandler { pub fn with(&mut self, handler: F) where F: Fn(T) -> R + 'static, - R: Responder + 'static, + R: Responder + 'static, T: FromRequest + 'static, { self.routes.push(Route::default()); @@ -259,7 +259,7 @@ impl ResourceHandler { where F: Fn(T) -> R + 'static, R: Future + 'static, - I: Responder + 'static, + I: Responder + 'static, E: Into + 'static, T: FromRequest + 'static, { diff --git a/src/route.rs b/src/route.rs index 44ac82807..a35a9f0b1 100644 --- a/src/route.rs +++ b/src/route.rs @@ -91,7 +91,7 @@ impl Route { pub fn f(&mut self, handler: F) where F: Fn(HttpRequest) -> R + 'static, - R: Responder + 'static, + R: Responder + 'static, { self.handler = InnerHandler::new(handler); } @@ -101,7 +101,7 @@ impl Route { where H: Fn(HttpRequest) -> F + 'static, F: Future + 'static, - R: Responder + 'static, + R: Responder + 'static, E: Into + 'static, { self.handler = InnerHandler::async(handler); @@ -167,7 +167,7 @@ impl Route { pub fn with(&mut self, handler: F) -> ExtractorConfig where F: Fn(T) -> R + 'static, - R: Responder + 'static, + R: Responder + 'static, T: FromRequest + 'static, { let cfg = ExtractorConfig::default(); @@ -208,7 +208,7 @@ impl Route { where F: Fn(T) -> R + 'static, R: Future + 'static, - I: Responder + 'static, + I: Responder + 'static, E: Into + 'static, T: FromRequest + 'static, { @@ -233,7 +233,7 @@ impl InnerHandler { where H: Fn(HttpRequest) -> F + 'static, F: Future + 'static, - R: Responder + 'static, + R: Responder + 'static, E: Into + 'static, { InnerHandler(Rc::new(UnsafeCell::new(Box::new(AsyncHandler::new(h))))) diff --git a/src/scope.rs b/src/scope.rs index a40113023..3a765c309 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -222,7 +222,7 @@ impl Scope { pub fn route(mut self, path: &str, method: Method, f: F) -> Scope where F: Fn(T) -> R + 'static, - R: Responder + 'static, + R: Responder + 'static, T: FromRequest + 'static, { // get resource handler diff --git a/src/test.rs b/src/test.rs index b8372f6a2..c1917811b 100644 --- a/src/test.rs +++ b/src/test.rs @@ -589,7 +589,7 @@ impl TestRequest { where H: Fn(HttpRequest) -> F + 'static, F: Future + 'static, - R: Responder + 'static, + R: Responder + 'static, E: Into + 'static, { let req = self.finish(); diff --git a/src/with.rs b/src/with.rs index c32f0a3bc..b2bbd5a96 100644 --- a/src/with.rs +++ b/src/with.rs @@ -134,7 +134,7 @@ where impl Handler for With where F: Fn(T) -> R + 'static, - R: Responder + 'static, + R: Responder + 'static, T: FromRequest + 'static, S: 'static, { @@ -161,7 +161,7 @@ where struct WithHandlerFut where F: Fn(T) -> R, - R: Responder, + R: Responder, T: FromRequest + 'static, S: 'static, { @@ -176,7 +176,7 @@ where impl Future for WithHandlerFut where F: Fn(T) -> R, - R: Responder + 'static, + R: Responder + 'static, T: FromRequest + 'static, S: 'static, { @@ -227,7 +227,7 @@ pub struct WithAsync where F: Fn(T) -> R, R: Future, - I: Responder, + I: Responder, E: Into, T: FromRequest, S: 'static, @@ -241,7 +241,7 @@ impl WithAsync where F: Fn(T) -> R, R: Future, - I: Responder, + I: Responder, E: Into, T: FromRequest, S: 'static, @@ -259,7 +259,7 @@ impl Handler for WithAsync where F: Fn(T) -> R + 'static, R: Future + 'static, - I: Responder + 'static, + I: Responder + 'static, E: Into + 'static, T: FromRequest + 'static, S: 'static, @@ -289,7 +289,7 @@ struct WithAsyncHandlerFut where F: Fn(T) -> R, R: Future + 'static, - I: Responder + 'static, + I: Responder + 'static, E: Into + 'static, T: FromRequest + 'static, S: 'static, @@ -307,7 +307,7 @@ impl Future for WithAsyncHandlerFut where F: Fn(T) -> R, R: Future + 'static, - I: Responder + 'static, + I: Responder + 'static, E: Into + 'static, T: FromRequest + 'static, S: 'static,