1
0
mirror of https://github.com/actix/actix-extras.git synced 2025-06-25 09:59:21 +02:00

add Item and Error to FromRequest trait

This commit is contained in:
Nikolay Kim
2017-12-03 14:22:04 -08:00
parent 6bc7d60f52
commit 7c6faaa8e0
14 changed files with 178 additions and 108 deletions

View File

@ -9,8 +9,8 @@
//! ```
// dev specific
pub use route::Handler;
pub use pipeline::Pipeline;
pub use route::{Handler, FromRequest};
pub use channel::{HttpChannel, HttpHandler};
pub use recognizer::{FromParam, RouteRecognizer};

View File

@ -31,7 +31,7 @@ use httpcodes::{HTTPBadRequest, HTTPMethodNotAllowed, HTTPExpectationFailed};
pub type Result<T> = result::Result<T, Error>;
/// General purpose actix web error
#[derive(Debug)]
#[derive(Fail, Debug)]
pub struct Error {
cause: Box<ResponseError>,
}

View File

@ -1,6 +1,6 @@
//! Static files support.
//!
//! TODO: needs to re-implement actual files handling, current impl blocks
// //! TODO: needs to re-implement actual files handling, current impl blocks
use std::io;
use std::io::Read;
use std::fmt::Write;
@ -19,11 +19,10 @@ use httpcodes::{HTTPOk, HTTPNotFound};
///
/// ```rust
/// extern crate actix_web;
/// use actix_web::*;
///
/// fn main() {
/// let app = Application::default("/")
/// .route("/static", StaticFiles::new(".", true))
/// let app = actix_web::Application::default("/")
/// .route("/static", actix_web::fs::StaticFiles::new(".", true))
/// .finish();
/// }
/// ```
@ -39,6 +38,7 @@ impl StaticFiles {
/// Create new `StaticFiles` instance
///
/// `dir` - base directory
///
/// `index` - show index for directory
pub fn new<D: Into<PathBuf>>(dir: D, index: bool) -> StaticFiles {
let dir = dir.into();

View File

@ -1,6 +1,6 @@
//! Basic http responses
#![allow(non_upper_case_globals)]
use http::StatusCode;
use http::{StatusCode, Error as HttpError};
use body::Body;
use route::{Reply, RouteHandler, FromRequest};
@ -74,8 +74,11 @@ impl<S> RouteHandler<S> for StaticResponse {
}
impl FromRequest for StaticResponse {
fn from_request(self, _: HttpRequest) -> Reply {
Reply::response(HttpResponse::new(self.0, Body::Empty))
type Item = HttpResponse;
type Error = HttpError;
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
self.build().body(Body::Empty)
}
}

View File

@ -8,11 +8,10 @@ use http::{StatusCode, Version, HeaderMap, HttpTryFrom, Error as HttpError};
use http::header::{self, HeaderName, HeaderValue};
use serde_json;
use serde::Serialize;
use Cookie;
use body::Body;
use error::Error;
use route::{Reply, FromRequest};
use route::FromRequest;
use encoding::ContentEncoding;
use httprequest::HttpRequest;
@ -461,8 +460,11 @@ impl From<HttpResponseBuilder> for HttpResponse {
}
impl FromRequest for HttpResponseBuilder {
fn from_request(self, _: HttpRequest) -> Reply {
Reply::response(self)
type Item = HttpResponse;
type Error = HttpError;
fn from_request(mut self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
self.finish()
}
}
@ -476,11 +478,13 @@ impl From<&'static str> for HttpResponse {
}
impl FromRequest for &'static str {
fn from_request(self, req: HttpRequest) -> Reply {
type Item = HttpResponse;
type Error = HttpError;
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
HttpResponse::build(StatusCode::OK)
.content_type("text/plain; charset=utf-8")
.body(self)
.from_request(req)
}
}
@ -494,11 +498,13 @@ impl From<&'static [u8]> for HttpResponse {
}
impl FromRequest for &'static [u8] {
fn from_request(self, req: HttpRequest) -> Reply {
type Item = HttpResponse;
type Error = HttpError;
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
HttpResponse::build(StatusCode::OK)
.content_type("application/octet-stream")
.body(self)
.from_request(req)
}
}
@ -512,11 +518,13 @@ impl From<String> for HttpResponse {
}
impl FromRequest for String {
fn from_request(self, req: HttpRequest) -> Reply {
type Item = HttpResponse;
type Error = HttpError;
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
HttpResponse::build(StatusCode::OK)
.content_type("text/plain; charset=utf-8")
.body(self)
.from_request(req)
}
}
@ -530,11 +538,13 @@ impl<'a> From<&'a String> for HttpResponse {
}
impl<'a> FromRequest for &'a String {
fn from_request(self, req: HttpRequest) -> Reply {
type Item = HttpResponse;
type Error = HttpError;
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
HttpResponse::build(StatusCode::OK)
.content_type("text/plain; charset=utf-8")
.body(self)
.from_request(req)
}
}
@ -548,11 +558,13 @@ impl From<Bytes> for HttpResponse {
}
impl FromRequest for Bytes {
fn from_request(self, req: HttpRequest) -> Reply {
type Item = HttpResponse;
type Error = HttpError;
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
HttpResponse::build(StatusCode::OK)
.content_type("application/octet-stream")
.body(self)
.from_request(req)
}
}
@ -566,11 +578,13 @@ impl From<BytesMut> for HttpResponse {
}
impl FromRequest for BytesMut {
fn from_request(self, req: HttpRequest) -> Reply {
type Item = HttpResponse;
type Error = HttpError;
fn from_request(self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
HttpResponse::build(StatusCode::OK)
.content_type("application/octet-stream")
.body(self)
.from_request(req)
}
}
@ -650,6 +664,8 @@ mod tests {
#[test]
fn test_into_response() {
let req = HttpRequest::default();
let resp: HttpResponse = "test".into();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
@ -657,6 +673,13 @@ mod tests {
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().binary().unwrap(), &Binary::from("test"));
let resp: HttpResponse = "test".from_request(req.clone()).ok().unwrap();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
header::HeaderValue::from_static("text/plain; charset=utf-8"));
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().binary().unwrap(), &Binary::from("test"));
let resp: HttpResponse = b"test".as_ref().into();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
@ -664,6 +687,13 @@ mod tests {
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().binary().unwrap(), &Binary::from(b"test".as_ref()));
let resp: HttpResponse = b"test".as_ref().from_request(req.clone()).ok().unwrap();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
header::HeaderValue::from_static("application/octet-stream"));
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().binary().unwrap(), &Binary::from(b"test".as_ref()));
let resp: HttpResponse = "test".to_owned().into();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
@ -671,6 +701,13 @@ mod tests {
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().binary().unwrap(), &Binary::from("test".to_owned()));
let resp: HttpResponse = "test".to_owned().from_request(req.clone()).ok().unwrap();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
header::HeaderValue::from_static("text/plain; charset=utf-8"));
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().binary().unwrap(), &Binary::from("test".to_owned()));
let resp: HttpResponse = (&"test".to_owned()).into();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
@ -678,6 +715,13 @@ mod tests {
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().binary().unwrap(), &Binary::from((&"test".to_owned())));
let resp: HttpResponse = (&"test".to_owned()).from_request(req.clone()).ok().unwrap();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
header::HeaderValue::from_static("text/plain; charset=utf-8"));
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().binary().unwrap(), &Binary::from((&"test".to_owned())));
let b = Bytes::from_static(b"test");
let resp: HttpResponse = b.into();
assert_eq!(resp.status(), StatusCode::OK);
@ -686,6 +730,14 @@ mod tests {
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().binary().unwrap(), &Binary::from(Bytes::from_static(b"test")));
let b = Bytes::from_static(b"test");
let resp: HttpResponse = b.from_request(req.clone()).ok().unwrap();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
header::HeaderValue::from_static("application/octet-stream"));
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().binary().unwrap(), &Binary::from(Bytes::from_static(b"test")));
let b = BytesMut::from("test");
let resp: HttpResponse = b.into();
assert_eq!(resp.status(), StatusCode::OK);
@ -693,5 +745,13 @@ mod tests {
header::HeaderValue::from_static("application/octet-stream"));
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().binary().unwrap(), &Binary::from(BytesMut::from("test")));
let b = BytesMut::from("test");
let resp: HttpResponse = b.from_request(req.clone()).ok().unwrap();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(),
header::HeaderValue::from_static("application/octet-stream"));
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().binary().unwrap(), &Binary::from(BytesMut::from("test")));
}
}

View File

@ -58,7 +58,6 @@ mod resource;
mod recognizer;
mod route;
mod pipeline;
mod fs;
mod server;
mod channel;
mod wsframe;
@ -68,6 +67,7 @@ mod h2;
mod h1writer;
mod h2writer;
pub mod fs;
pub mod ws;
pub mod dev;
pub mod error;
@ -81,12 +81,11 @@ pub use application::Application;
pub use httprequest::{HttpRequest, UrlEncoded};
pub use httpresponse::HttpResponse;
pub use payload::{Payload, PayloadItem};
pub use route::Reply;
pub use route::{Reply, FromRequest};
pub use resource::Resource;
pub use recognizer::Params;
pub use server::HttpServer;
pub use context::HttpContext;
pub use fs::StaticFiles;
// re-exports
pub use http::{Method, StatusCode, Version};

View File

@ -1,5 +1,4 @@
use std::marker::PhantomData;
use std::result::Result as StdResult;
use actix::Actor;
use futures::Future;
@ -21,7 +20,13 @@ pub trait Handler<S>: 'static {
}
pub trait FromRequest {
fn from_request(self, req: HttpRequest) -> Reply;
/// The associated item which can be returned.
type Item: Into<Reply>;
/// The associated error which can be returned.
type Error: Into<Error>;
fn from_request(self, req: HttpRequest) -> Result<Self::Item, Self::Error>;
}
/// Handler<S> for Fn()
@ -72,46 +77,53 @@ impl Reply {
}
impl FromRequest for Reply {
fn from_request(self, _: HttpRequest) -> Reply {
self
type Item = Reply;
type Error = Error;
fn from_request(self, _: HttpRequest) -> Result<Reply, Error> {
Ok(self)
}
}
impl FromRequest for HttpResponse {
fn from_request(self, _: HttpRequest) -> Reply {
Reply(ReplyItem::Message(self))
type Item = Reply;
type Error = Error;
fn from_request(self, _: HttpRequest) -> Result<Reply, Error> {
Ok(Reply(ReplyItem::Message(self)))
}
}
#[cfg(actix_nightly)]
default impl<T: FromRequest> FromRequest for T
{
fn from_request(self, req: HttpRequest) -> Reply {
self.from_request(req)
impl From<HttpResponse> for Reply {
fn from(resp: HttpResponse) -> Reply {
Reply(ReplyItem::Message(resp))
}
}
#[cfg(actix_nightly)]
default impl<T: Into<HttpResponse>, E: Into<Error>> FromRequest for StdResult<T, E> {
fn from_request(self, req: HttpRequest) -> Reply {
impl<T: Into<HttpResponse>, E: Into<Error>> FromRequest for Result<T, E> {
type Item = Reply;
type Error = E;
fn from_request(self, _: HttpRequest) -> Result<Reply, Self::Error> {
match self {
Ok(val) => Reply(ReplyItem::Message(val.into())), //val.from_request(req),
Err(err) => Reply(ReplyItem::Message(err.into().into())),
Ok(val) => Ok(Reply(ReplyItem::Message(val.into()))),
Err(err) => Err(err),
}
}
}
impl<E: Into<Error>> FromRequest for StdResult<Reply, E> {
fn from_request(self, _: HttpRequest) -> Reply {
match self {
Ok(val) => val,
Err(err) => Reply(ReplyItem::Message(err.into().into())),
}
impl<E: Into<Error>> FromRequest for Result<Reply, E> {
type Item = Reply;
type Error = E;
fn from_request(self, _: HttpRequest) -> Result<Reply, E> {
self
}
}
impl<E: Into<Error>> From<StdResult<Reply, E>> for Reply {
fn from(res: StdResult<Reply, E>) -> Self {
impl<E: Into<Error>> From<Result<Reply, E>> for Reply {
fn from(res: Result<Reply, E>) -> Self {
match res {
Ok(val) => val,
Err(err) => Reply(ReplyItem::Message(err.into().into())),
@ -119,23 +131,18 @@ impl<E: Into<Error>> From<StdResult<Reply, E>> for Reply {
}
}
impl<E: Into<Error>> FromRequest for StdResult<HttpResponse, E> {
fn from_request(self, _: HttpRequest) -> Reply {
match self {
Ok(val) => Reply(ReplyItem::Message(val)),
Err(err) => Reply(ReplyItem::Message(err.into().into())),
}
}
}
impl<A: Actor<Context=HttpContext<A, S>>, S: 'static> FromRequest for HttpContext<A, S>
{
fn from_request(self, _: HttpRequest) -> Reply {
Reply(ReplyItem::Actor(Box::new(self)))
type Item = Reply;
type Error = Error;
fn from_request(self, _: HttpRequest) -> Result<Reply, Error> {
Ok(Reply(ReplyItem::Actor(Box::new(self))))
}
}
impl<A: Actor<Context=HttpContext<A, S>>, S: 'static> From<HttpContext<A, S>> for Reply {
fn from(ctx: HttpContext<A, S>) -> Reply {
Reply(ReplyItem::Actor(Box::new(ctx)))
}
@ -143,8 +150,11 @@ impl<A: Actor<Context=HttpContext<A, S>>, S: 'static> From<HttpContext<A, S>> fo
impl FromRequest for Box<Future<Item=HttpResponse, Error=Error>>
{
fn from_request(self, _: HttpRequest) -> Reply {
Reply(ReplyItem::Future(self))
type Item = Reply;
type Error = Error;
fn from_request(self, _: HttpRequest) -> Result<Reply, Error> {
Ok(Reply(ReplyItem::Future(self)))
}
}
@ -181,7 +191,10 @@ impl<S, H, R> RouteHandler<S> for WrapHandler<S, H, R>
{
fn handle(&self, req: HttpRequest<S>) -> Reply {
let req2 = req.clone_without_state();
self.h.handle(req).from_request(req2)
match self.h.handle(req).from_request(req2) {
Ok(reply) => reply.into(),
Err(err) => Reply::response(err.into()),
}
}
}