1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-30 18:34:36 +01:00

use actix_web::Error for middleware errors

This commit is contained in:
Nikolay Kim 2019-03-10 16:35:38 -07:00
parent 79875ea039
commit 4d96abb639
13 changed files with 305 additions and 85 deletions

View File

@ -3,8 +3,6 @@ use std::marker::PhantomData;
use std::rc::Rc; use std::rc::Rc;
use actix_http::body::{Body, MessageBody}; use actix_http::body::{Body, MessageBody};
use actix_http::PayloadStream;
use actix_router::ResourceDef;
use actix_server_config::ServerConfig; use actix_server_config::ServerConfig;
use actix_service::boxed::{self, BoxedNewService}; use actix_service::boxed::{self, BoxedNewService};
use actix_service::{ use actix_service::{
@ -14,6 +12,8 @@ use futures::IntoFuture;
use crate::app_service::{AppChain, AppEntry, AppInit, AppRouting, AppRoutingFactory}; use crate::app_service::{AppChain, AppEntry, AppInit, AppRouting, AppRoutingFactory};
use crate::config::{AppConfig, AppConfigInner}; use crate::config::{AppConfig, AppConfigInner};
use crate::dev::{PayloadStream, ResourceDef};
use crate::error::Error;
use crate::resource::Resource; use crate::resource::Resource;
use crate::route::Route; use crate::route::Route;
use crate::service::{ use crate::service::{
@ -22,7 +22,8 @@ use crate::service::{
}; };
use crate::state::{State, StateFactory}; use crate::state::{State, StateFactory};
type HttpNewService<P> = BoxedNewService<(), ServiceRequest<P>, ServiceResponse, (), ()>; type HttpNewService<P> =
BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;
/// Application builder - structure that follows the builder pattern /// Application builder - structure that follows the builder pattern
/// for building application instances. /// for building application instances.
@ -55,7 +56,7 @@ where
T: NewService< T: NewService<
Request = ServiceRequest, Request = ServiceRequest,
Response = ServiceRequest<P>, Response = ServiceRequest<P>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
{ {
@ -118,7 +119,7 @@ where
impl NewService< impl NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
> >
@ -127,7 +128,7 @@ where
AppRouting<P>, AppRouting<P>,
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
F: IntoTransform<M, AppRouting<P>>, F: IntoTransform<M, AppRouting<P>>,
@ -157,7 +158,7 @@ where
impl NewService< impl NewService<
Request = ServiceRequest, Request = ServiceRequest,
Response = ServiceRequest<P1>, Response = ServiceRequest<P1>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
> >
@ -165,7 +166,7 @@ where
C: NewService< C: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceRequest<P1>, Response = ServiceRequest<P1>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
F: IntoNewService<C>, F: IntoNewService<C>,
@ -264,7 +265,7 @@ where
T: NewService< T: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
{ {
@ -324,7 +325,7 @@ where
impl NewService< impl NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse<B1>, Response = ServiceResponse<B1>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
> >
@ -333,7 +334,7 @@ where
T::Service, T::Service,
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse<B1>, Response = ServiceResponse<B1>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
B1: MessageBody, B1: MessageBody,
@ -363,7 +364,7 @@ where
U: NewService< U: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse, Response = ServiceResponse,
Error = (), Error = Error,
InitError = (), InitError = (),
> + 'static, > + 'static,
{ {
@ -415,13 +416,13 @@ where
T: NewService< T: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
C: NewService< C: NewService<
Request = ServiceRequest, Request = ServiceRequest,
Response = ServiceRequest<P>, Response = ServiceRequest<P>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
{ {

View File

@ -11,15 +11,17 @@ use futures::future::{ok, Either, FutureResult};
use futures::{Async, Future, Poll}; use futures::{Async, Future, Poll};
use crate::config::{AppConfig, ServiceConfig}; use crate::config::{AppConfig, ServiceConfig};
use crate::error::Error;
use crate::guard::Guard; use crate::guard::Guard;
use crate::rmap::ResourceMap; use crate::rmap::ResourceMap;
use crate::service::{ServiceFactory, ServiceRequest, ServiceResponse}; use crate::service::{ServiceFactory, ServiceRequest, ServiceResponse};
use crate::state::{StateFactory, StateFactoryResult}; use crate::state::{StateFactory, StateFactoryResult};
type Guards = Vec<Box<Guard>>; type Guards = Vec<Box<Guard>>;
type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, ()>; type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, Error>;
type HttpNewService<P> = BoxedNewService<(), ServiceRequest<P>, ServiceResponse, (), ()>; type HttpNewService<P> =
type BoxedResponse = Box<Future<Item = ServiceResponse, Error = ()>>; BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;
type BoxedResponse = Box<Future<Item = ServiceResponse, Error = Error>>;
/// Service factory to convert `Request` to a `ServiceRequest<S>`. /// Service factory to convert `Request` to a `ServiceRequest<S>`.
/// It also executes state factories. /// It also executes state factories.
@ -29,7 +31,7 @@ where
T: NewService< T: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
{ {
@ -48,13 +50,13 @@ where
C: NewService< C: NewService<
Request = ServiceRequest, Request = ServiceRequest,
Response = ServiceRequest<P>, Response = ServiceRequest<P>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
T: NewService< T: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
{ {
@ -147,13 +149,13 @@ where
C: NewService< C: NewService<
Request = ServiceRequest, Request = ServiceRequest,
Response = ServiceRequest<P>, Response = ServiceRequest<P>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
T: NewService< T: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse<B>, Response = ServiceResponse<B>,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
{ {
@ -201,7 +203,7 @@ where
/// Service to convert `Request` to a `ServiceRequest<S>` /// Service to convert `Request` to a `ServiceRequest<S>`
pub struct AppInitService<C, P> pub struct AppInitService<C, P>
where where
C: Service<Request = ServiceRequest, Response = ServiceRequest<P>, Error = ()>, C: Service<Request = ServiceRequest, Response = ServiceRequest<P>, Error = Error>,
{ {
chain: C, chain: C,
rmap: Rc<ResourceMap>, rmap: Rc<ResourceMap>,
@ -210,7 +212,7 @@ where
impl<C, P> Service for AppInitService<C, P> impl<C, P> Service for AppInitService<C, P>
where where
C: Service<Request = ServiceRequest, Response = ServiceRequest<P>, Error = ()>, C: Service<Request = ServiceRequest, Response = ServiceRequest<P>, Error = Error>,
{ {
type Request = Request; type Request = Request;
type Response = ServiceRequest<P>; type Response = ServiceRequest<P>;
@ -240,7 +242,7 @@ pub struct AppRoutingFactory<P> {
impl<P: 'static> NewService for AppRoutingFactory<P> { impl<P: 'static> NewService for AppRoutingFactory<P> {
type Request = ServiceRequest<P>; type Request = ServiceRequest<P>;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type InitError = (); type InitError = ();
type Service = AppRouting<P>; type Service = AppRouting<P>;
type Future = AppRoutingFactoryResponse<P>; type Future = AppRoutingFactoryResponse<P>;
@ -350,7 +352,7 @@ pub struct AppRouting<P> {
impl<P> Service for AppRouting<P> { impl<P> Service for AppRouting<P> {
type Request = ServiceRequest<P>; type Request = ServiceRequest<P>;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type Future = Either<BoxedResponse, FutureResult<Self::Response, Self::Error>>; type Future = Either<BoxedResponse, FutureResult<Self::Response, Self::Error>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> { fn poll_ready(&mut self) -> Poll<(), Self::Error> {
@ -398,7 +400,7 @@ impl<P> AppEntry<P> {
impl<P: 'static> NewService for AppEntry<P> { impl<P: 'static> NewService for AppEntry<P> {
type Request = ServiceRequest<P>; type Request = ServiceRequest<P>;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type InitError = (); type InitError = ();
type Service = AppRouting<P>; type Service = AppRouting<P>;
type Future = AppRoutingFactoryResponse<P>; type Future = AppRoutingFactoryResponse<P>;
@ -414,7 +416,7 @@ pub struct AppChain;
impl NewService for AppChain { impl NewService for AppChain {
type Request = ServiceRequest; type Request = ServiceRequest;
type Response = ServiceRequest; type Response = ServiceRequest;
type Error = (); type Error = Error;
type InitError = (); type InitError = ();
type Service = AppChain; type Service = AppChain;
type Future = FutureResult<Self::Service, Self::InitError>; type Future = FutureResult<Self::Service, Self::InitError>;
@ -427,7 +429,7 @@ impl NewService for AppChain {
impl Service for AppChain { impl Service for AppChain {
type Request = ServiceRequest; type Request = ServiceRequest;
type Response = ServiceRequest; type Response = ServiceRequest;
type Error = (); type Error = Error;
type Future = FutureResult<Self::Response, Self::Error>; type Future = FutureResult<Self::Response, Self::Error>;
#[inline] #[inline]

View File

@ -6,13 +6,14 @@ use actix_http::Extensions;
use actix_router::ResourceDef; use actix_router::ResourceDef;
use actix_service::{boxed, IntoNewService, NewService}; use actix_service::{boxed, IntoNewService, NewService};
use crate::error::Error;
use crate::guard::Guard; use crate::guard::Guard;
use crate::rmap::ResourceMap; use crate::rmap::ResourceMap;
use crate::service::{ServiceRequest, ServiceResponse}; use crate::service::{ServiceRequest, ServiceResponse};
type Guards = Vec<Box<Guard>>; type Guards = Vec<Box<Guard>>;
type HttpNewService<P> = type HttpNewService<P> =
boxed::BoxedNewService<(), ServiceRequest<P>, ServiceResponse, (), ()>; boxed::BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;
/// Application configuration /// Application configuration
pub struct ServiceConfig<P> { pub struct ServiceConfig<P> {
@ -84,7 +85,7 @@ impl<P: 'static> ServiceConfig<P> {
S: NewService< S: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse, Response = ServiceResponse,
Error = (), Error = Error,
InitError = (), InitError = (),
> + 'static, > + 'static,
{ {

View File

@ -193,7 +193,7 @@ where
{ {
type Request = (T, HttpRequest); type Request = (T, HttpRequest);
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type InitError = (); type InitError = ();
type Service = AsyncHandlerService<F, T, R>; type Service = AsyncHandlerService<F, T, R>;
type Future = FutureResult<Self::Service, ()>; type Future = FutureResult<Self::Service, ()>;
@ -227,7 +227,7 @@ where
{ {
type Request = (T, HttpRequest); type Request = (T, HttpRequest);
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type Future = AsyncHandlerServiceResponse<R::Future>; type Future = AsyncHandlerServiceResponse<R::Future>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> { fn poll_ready(&mut self) -> Poll<(), Self::Error> {
@ -255,7 +255,7 @@ where
T::Error: Into<Error>, T::Error: Into<Error>,
{ {
type Item = ServiceResponse; type Item = ServiceResponse;
type Error = (); type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
match self.fut.poll() { match self.fut.poll() {

View File

@ -40,7 +40,6 @@ pub use crate::responder::{Either, Responder};
pub use crate::route::Route; pub use crate::route::Route;
pub use crate::scope::Scope; pub use crate::scope::Scope;
pub use crate::server::HttpServer; pub use crate::server::HttpServer;
pub use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};
pub mod dev { pub mod dev {
//! The `actix-web` prelude for library developers //! The `actix-web` prelude for library developers
@ -58,7 +57,9 @@ pub mod dev {
pub use crate::config::{AppConfig, ServiceConfig}; pub use crate::config::{AppConfig, ServiceConfig};
pub use crate::info::ConnectionInfo; pub use crate::info::ConnectionInfo;
pub use crate::rmap::ResourceMap; pub use crate::rmap::ResourceMap;
pub use crate::service::HttpServiceFactory; pub use crate::service::{
HttpServiceFactory, ServiceFromRequest, ServiceRequest, ServiceResponse,
};
pub use actix_http::body::{Body, BodyLength, MessageBody, ResponseBody}; pub use actix_http::body::{Body, BodyLength, MessageBody, ResponseBody};
pub use actix_http::dev::ResponseBuilder as HttpResponseBuilder; pub use actix_http::dev::ResponseBuilder as HttpResponseBuilder;

View File

@ -152,9 +152,10 @@ mod tests {
use actix_service::FnService; use actix_service::FnService;
use super::*; use super::*;
use crate::dev::ServiceRequest;
use crate::http::header::CONTENT_TYPE; use crate::http::header::CONTENT_TYPE;
use crate::test::{block_on, TestRequest}; use crate::test::{block_on, TestRequest};
use crate::{HttpResponse, ServiceRequest}; use crate::HttpResponse;
#[test] #[test]
fn test_default_headers() { fn test_default_headers() {

View File

@ -0,0 +1,210 @@
use std::rc::Rc;
use actix_service::{Service, Transform};
use futures::future::{err, ok, Either, Future, FutureResult};
use futures::Poll;
use hashbrown::HashMap;
use crate::dev::{ServiceRequest, ServiceResponse};
use crate::error::{Error, Result};
use crate::http::StatusCode;
/// Error handler response
pub enum ErrorHandlerResponse<B> {
/// New http response got generated
Response(ServiceResponse<B>),
/// Result is a future that resolves to a new http response
Future(Box<Future<Item = ServiceResponse<B>, Error = Error>>),
}
type ErrorHandler<B> = Fn(ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>>;
/// `Middleware` for allowing custom handlers for responses.
///
/// You can use `ErrorHandlers::handler()` method to register a custom error
/// handler for specific status code. You can modify existing response or
/// create completely new one.
///
/// ## Example
///
/// ```rust
/// use actix_web::middleware::{ErrorHandlers, ErrorHandlerResponse};
/// use actix_web::{web, http, dev, App, HttpRequest, HttpResponse, Result};
///
/// fn render_500<B>(mut res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
/// res.response_mut()
/// .headers_mut()
/// .insert(http::header::CONTENT_TYPE, http::HeaderValue::from_static("Error"));
/// Ok(ErrorHandlerResponse::Response(res))
/// }
///
/// fn main() {
/// let app = App::new()
/// .middleware(
/// ErrorHandlers::new()
/// .handler(http::StatusCode::INTERNAL_SERVER_ERROR, render_500),
/// )
/// .service(web::resource("/test")
/// .route(web::get().to(|| HttpResponse::Ok()))
/// .route(web::head().to(|| HttpResponse::MethodNotAllowed())
/// ));
/// }
/// ```
pub struct ErrorHandlers<B> {
handlers: Rc<HashMap<StatusCode, Box<ErrorHandler<B>>>>,
}
impl<B> Default for ErrorHandlers<B> {
fn default() -> Self {
ErrorHandlers {
handlers: Rc::new(HashMap::new()),
}
}
}
impl<B> ErrorHandlers<B> {
/// Construct new `ErrorHandlers` instance
pub fn new() -> Self {
ErrorHandlers::default()
}
/// Register error handler for specified status code
pub fn handler<F>(mut self, status: StatusCode, handler: F) -> Self
where
F: Fn(ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> + 'static,
{
Rc::get_mut(&mut self.handlers)
.unwrap()
.insert(status, Box::new(handler));
self
}
}
impl<S, P, B> Transform<S> for ErrorHandlers<B>
where
S: Service<
Request = ServiceRequest<P>,
Response = ServiceResponse<B>,
Error = Error,
>,
S::Future: 'static,
S::Error: 'static,
B: 'static,
{
type Request = ServiceRequest<P>;
type Response = ServiceResponse<B>;
type Error = Error;
type InitError = ();
type Transform = ErrorHandlersMiddleware<S, B>;
type Future = FutureResult<Self::Transform, Self::InitError>;
fn new_transform(&self, service: S) -> Self::Future {
ok(ErrorHandlersMiddleware {
service,
handlers: self.handlers.clone(),
})
}
}
pub struct ErrorHandlersMiddleware<S, B> {
service: S,
handlers: Rc<HashMap<StatusCode, Box<ErrorHandler<B>>>>,
}
impl<S, P, B> Service for ErrorHandlersMiddleware<S, B>
where
S: Service<
Request = ServiceRequest<P>,
Response = ServiceResponse<B>,
Error = Error,
>,
S::Future: 'static,
S::Error: 'static,
B: 'static,
{
type Request = ServiceRequest<P>;
type Response = ServiceResponse<B>;
type Error = Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.service.poll_ready()
}
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {
let handlers = self.handlers.clone();
Box::new(self.service.call(req).and_then(move |res| {
if let Some(handler) = handlers.get(&res.status()) {
match handler(res) {
Ok(ErrorHandlerResponse::Response(res)) => Either::A(ok(res)),
Ok(ErrorHandlerResponse::Future(fut)) => Either::B(fut),
Err(e) => Either::A(err(e)),
}
} else {
Either::A(ok(res))
}
}))
}
}
#[cfg(test)]
mod tests {
use actix_service::FnService;
use futures::future::ok;
use super::*;
use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
use crate::test::{self, TestRequest};
use crate::HttpResponse;
fn render_500<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
res.response_mut()
.headers_mut()
.insert(CONTENT_TYPE, HeaderValue::from_static("0001"));
Ok(ErrorHandlerResponse::Response(res))
}
#[test]
fn test_handler() {
let srv = FnService::new(|req: ServiceRequest<_>| {
req.into_response(HttpResponse::InternalServerError().finish())
});
let mut mw = test::block_on(
ErrorHandlers::new()
.handler(StatusCode::INTERNAL_SERVER_ERROR, render_500)
.new_transform(srv),
)
.unwrap();
let resp = test::call_success(&mut mw, TestRequest::default().to_service());
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
}
fn render_500_async<B: 'static>(
mut res: ServiceResponse<B>,
) -> Result<ErrorHandlerResponse<B>> {
res.response_mut()
.headers_mut()
.insert(CONTENT_TYPE, HeaderValue::from_static("0001"));
Ok(ErrorHandlerResponse::Future(Box::new(ok(res))))
}
#[test]
fn test_handler_async() {
let srv = FnService::new(|req: ServiceRequest<_>| {
req.into_response(HttpResponse::InternalServerError().finish())
});
let mut mw = test::block_on(
ErrorHandlers::new()
.handler(StatusCode::INTERNAL_SERVER_ERROR, render_500_async)
.new_transform(srv),
)
.unwrap();
let resp = test::call_success(&mut mw, TestRequest::default().to_service());
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
}
}

View File

@ -4,13 +4,15 @@ mod compress;
pub use self::compress::Compress; pub use self::compress::Compress;
mod defaultheaders; mod defaultheaders;
mod errhandlers;
mod logger;
pub use self::defaultheaders::DefaultHeaders; pub use self::defaultheaders::DefaultHeaders;
pub use self::errhandlers::{ErrorHandlerResponse, ErrorHandlers};
pub use self::logger::Logger;
// #[cfg(feature = "session")] // #[cfg(feature = "session")]
// pub use actix_session as session; // pub use actix_session as session;
mod logger;
pub use self::logger::Logger;
#[cfg(feature = "session")] #[cfg(feature = "session")]
pub mod identity; pub mod identity;

View File

@ -17,8 +17,9 @@ use crate::responder::Responder;
use crate::route::{CreateRouteService, Route, RouteService}; use crate::route::{CreateRouteService, Route, RouteService};
use crate::service::{ServiceRequest, ServiceResponse}; use crate::service::{ServiceRequest, ServiceResponse};
type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, ()>; type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, Error>;
type HttpNewService<P> = BoxedNewService<(), ServiceRequest<P>, ServiceResponse, (), ()>; type HttpNewService<P> =
BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;
/// *Resource* is an entry in route table which corresponds to requested URL. /// *Resource* is an entry in route table which corresponds to requested URL.
/// ///
@ -70,7 +71,7 @@ where
T: NewService< T: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse, Response = ServiceResponse,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
{ {
@ -232,7 +233,7 @@ where
impl NewService< impl NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse, Response = ServiceResponse,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
> >
@ -241,7 +242,7 @@ where
T::Service, T::Service,
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse, Response = ServiceResponse,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
F: IntoTransform<M, T::Service>, F: IntoTransform<M, T::Service>,
@ -266,7 +267,7 @@ where
U: NewService< U: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse, Response = ServiceResponse,
Error = (), Error = Error,
> + 'static, > + 'static,
{ {
// create and configure default resource // create and configure default resource
@ -284,7 +285,7 @@ where
T: NewService< T: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse, Response = ServiceResponse,
Error = (), Error = Error,
InitError = (), InitError = (),
> + 'static, > + 'static,
{ {
@ -314,7 +315,7 @@ where
T: NewService< T: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse, Response = ServiceResponse,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
{ {
@ -336,7 +337,7 @@ pub struct ResourceFactory<P> {
impl<P: 'static> NewService for ResourceFactory<P> { impl<P: 'static> NewService for ResourceFactory<P> {
type Request = ServiceRequest<P>; type Request = ServiceRequest<P>;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type InitError = (); type InitError = ();
type Service = ResourceService<P>; type Service = ResourceService<P>;
type Future = CreateResourceService<P>; type Future = CreateResourceService<P>;
@ -427,9 +428,9 @@ pub struct ResourceService<P> {
impl<P> Service for ResourceService<P> { impl<P> Service for ResourceService<P> {
type Request = ServiceRequest<P>; type Request = ServiceRequest<P>;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type Future = Either< type Future = Either<
Box<Future<Item = ServiceResponse, Error = ()>>, Box<Future<Item = ServiceResponse, Error = Error>>,
Either< Either<
Box<Future<Item = Self::Response, Error = Self::Error>>, Box<Future<Item = Self::Response, Error = Self::Error>>,
FutureResult<Self::Response, Self::Error>, FutureResult<Self::Response, Self::Error>,
@ -472,7 +473,7 @@ impl<P> ResourceEndpoint<P> {
impl<P: 'static> NewService for ResourceEndpoint<P> { impl<P: 'static> NewService for ResourceEndpoint<P> {
type Request = ServiceRequest<P>; type Request = ServiceRequest<P>;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type InitError = (); type InitError = ();
type Service = ResourceService<P>; type Service = ResourceService<P>;
type Future = CreateResourceService<P>; type Future = CreateResourceService<P>;

View File

@ -17,8 +17,8 @@ type BoxedRouteService<Req, Res> = Box<
Service< Service<
Request = Req, Request = Req,
Response = Res, Response = Res,
Error = (), Error = Error,
Future = Box<Future<Item = Res, Error = ()>>, Future = Box<Future<Item = Res, Error = Error>>,
>, >,
>; >;
@ -26,7 +26,7 @@ type BoxedRouteNewService<Req, Res> = Box<
NewService< NewService<
Request = Req, Request = Req,
Response = Res, Response = Res,
Error = (), Error = Error,
InitError = (), InitError = (),
Service = BoxedRouteService<Req, Res>, Service = BoxedRouteService<Req, Res>,
Future = Box<Future<Item = BoxedRouteService<Req, Res>, Error = ()>>, Future = Box<Future<Item = BoxedRouteService<Req, Res>, Error = ()>>,
@ -73,7 +73,7 @@ impl<P: 'static> Route<P> {
impl<P> NewService for Route<P> { impl<P> NewService for Route<P> {
type Request = ServiceRequest<P>; type Request = ServiceRequest<P>;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type InitError = (); type InitError = ();
type Service = RouteService<P>; type Service = RouteService<P>;
type Future = CreateRouteService<P>; type Future = CreateRouteService<P>;
@ -129,7 +129,7 @@ impl<P> RouteService<P> {
impl<P> Service for RouteService<P> { impl<P> Service for RouteService<P> {
type Request = ServiceRequest<P>; type Request = ServiceRequest<P>;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>; type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> { fn poll_ready(&mut self) -> Poll<(), Self::Error> {
@ -188,7 +188,7 @@ impl<P: 'static> Route<P> {
// T: NewService< // T: NewService<
// Request = HandlerRequest<S>, // Request = HandlerRequest<S>,
// Response = HandlerRequest<S, U>, // Response = HandlerRequest<S, U>,
// InitError = (), // InitError = Error,
// >, // >,
// { // {
// RouteServiceBuilder { // RouteServiceBuilder {
@ -372,7 +372,7 @@ where
{ {
type Request = ServiceRequest<P>; type Request = ServiceRequest<P>;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type InitError = (); type InitError = ();
type Service = BoxedRouteService<ServiceRequest<P>, Self::Response>; type Service = BoxedRouteService<ServiceRequest<P>, Self::Response>;
type Future = Box<Future<Item = Self::Service, Error = Self::InitError>>; type Future = Box<Future<Item = Self::Service, Error = Self::InitError>>;
@ -410,11 +410,11 @@ where
{ {
type Request = ServiceRequest<P>; type Request = ServiceRequest<P>;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>; type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> { fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.service.poll_ready().map_err(|_| ()) self.service.poll_ready().map_err(|(e, _)| e)
} }
fn call(&mut self, req: ServiceRequest<P>) -> Self::Future { fn call(&mut self, req: ServiceRequest<P>) -> Self::Future {

View File

@ -11,6 +11,7 @@ use futures::future::{ok, Either, Future, FutureResult};
use futures::{Async, Poll}; use futures::{Async, Poll};
use crate::dev::{HttpServiceFactory, ServiceConfig}; use crate::dev::{HttpServiceFactory, ServiceConfig};
use crate::error::Error;
use crate::guard::Guard; use crate::guard::Guard;
use crate::resource::Resource; use crate::resource::Resource;
use crate::rmap::ResourceMap; use crate::rmap::ResourceMap;
@ -20,9 +21,10 @@ use crate::service::{
}; };
type Guards = Vec<Box<Guard>>; type Guards = Vec<Box<Guard>>;
type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, ()>; type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, Error>;
type HttpNewService<P> = BoxedNewService<(), ServiceRequest<P>, ServiceResponse, (), ()>; type HttpNewService<P> =
type BoxedResponse = Box<Future<Item = ServiceResponse, Error = ()>>; BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;
type BoxedResponse = Box<Future<Item = ServiceResponse, Error = Error>>;
/// Resources scope /// Resources scope
/// ///
@ -83,7 +85,7 @@ where
T: NewService< T: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse, Response = ServiceResponse,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
{ {
@ -176,7 +178,7 @@ where
U: NewService< U: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse, Response = ServiceResponse,
Error = (), Error = Error,
InitError = (), InitError = (),
> + 'static, > + 'static,
{ {
@ -201,7 +203,7 @@ where
impl NewService< impl NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse, Response = ServiceResponse,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
> >
@ -210,7 +212,7 @@ where
T::Service, T::Service,
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse, Response = ServiceResponse,
Error = (), Error = Error,
InitError = (), InitError = (),
>, >,
F: IntoTransform<M, T::Service>, F: IntoTransform<M, T::Service>,
@ -233,7 +235,7 @@ where
T: NewService< T: NewService<
Request = ServiceRequest<P>, Request = ServiceRequest<P>,
Response = ServiceResponse, Response = ServiceResponse,
Error = (), Error = Error,
InitError = (), InitError = (),
> + 'static, > + 'static,
{ {
@ -290,7 +292,7 @@ pub struct ScopeFactory<P> {
impl<P: 'static> NewService for ScopeFactory<P> { impl<P: 'static> NewService for ScopeFactory<P> {
type Request = ServiceRequest<P>; type Request = ServiceRequest<P>;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type InitError = (); type InitError = ();
type Service = ScopeService<P>; type Service = ScopeService<P>;
type Future = ScopeFactoryResponse<P>; type Future = ScopeFactoryResponse<P>;
@ -406,7 +408,7 @@ pub struct ScopeService<P> {
impl<P> Service for ScopeService<P> { impl<P> Service for ScopeService<P> {
type Request = ServiceRequest<P>; type Request = ServiceRequest<P>;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type Future = Either<BoxedResponse, FutureResult<Self::Response, Self::Error>>; type Future = Either<BoxedResponse, FutureResult<Self::Response, Self::Error>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> { fn poll_ready(&mut self) -> Poll<(), Self::Error> {
@ -450,7 +452,7 @@ impl<P> ScopeEndpoint<P> {
impl<P: 'static> NewService for ScopeEndpoint<P> { impl<P: 'static> NewService for ScopeEndpoint<P> {
type Request = ServiceRequest<P>; type Request = ServiceRequest<P>;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = (); type Error = Error;
type InitError = (); type InitError = ();
type Service = ScopeService<P>; type Service = ScopeService<P>;
type Future = ScopeFactoryResponse<P>; type Future = ScopeFactoryResponse<P>;

View File

@ -340,6 +340,12 @@ impl<B> ServiceResponse<B> {
Self::from_err(err, self.request) Self::from_err(err, self.request)
} }
/// Create service response
#[inline]
pub fn into_response<B1>(self, response: Response<B1>) -> ServiceResponse<B1> {
ServiceResponse::new(self.request, response)
}
/// Get reference to original request /// Get reference to original request
#[inline] #[inline]
pub fn request(&self) -> &HttpRequest { pub fn request(&self) -> &HttpRequest {
@ -358,18 +364,6 @@ impl<B> ServiceResponse<B> {
&mut self.response &mut self.response
} }
/// Get the headers from the response
#[inline]
pub fn headers(&self) -> &HeaderMap {
self.response.headers()
}
/// Get a mutable reference to the headers
#[inline]
pub fn headers_mut(&mut self) -> &mut HeaderMap {
self.response.headers_mut()
}
/// Execute closure and in case of error convert it to response. /// Execute closure and in case of error convert it to response.
pub fn checked_expr<F, E>(mut self, f: F) -> Self pub fn checked_expr<F, E>(mut self, f: F) -> Self
where where

View File

@ -14,9 +14,9 @@ use bytes::Bytes;
use futures::Future; use futures::Future;
use crate::config::{AppConfig, AppConfigInner}; use crate::config::{AppConfig, AppConfigInner};
use crate::request::HttpRequest;
use crate::rmap::ResourceMap; use crate::rmap::ResourceMap;
use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse}; use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};
use crate::{HttpRequest, HttpResponse};
thread_local! { thread_local! {
static RT: RefCell<Runtime> = { static RT: RefCell<Runtime> = {
@ -277,6 +277,11 @@ impl TestRequest {
self.req.finish() self.req.finish()
} }
/// Complete request creation and generate `ServiceResponse` instance
pub fn to_response<B>(self, res: HttpResponse<B>) -> ServiceResponse<B> {
self.to_service().into_response(res)
}
/// Complete request creation and generate `HttpRequest` instance /// Complete request creation and generate `HttpRequest` instance
pub fn to_http_request(mut self) -> HttpRequest { pub fn to_http_request(mut self) -> HttpRequest {
let req = self.req.finish(); let req = self.req.finish();