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

View File

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

View File

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

View File

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

View File

@ -40,7 +40,6 @@ pub use crate::responder::{Either, Responder};
pub use crate::route::Route;
pub use crate::scope::Scope;
pub use crate::server::HttpServer;
pub use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};
pub mod dev {
//! The `actix-web` prelude for library developers
@ -58,7 +57,9 @@ pub mod dev {
pub use crate::config::{AppConfig, ServiceConfig};
pub use crate::info::ConnectionInfo;
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::dev::ResponseBuilder as HttpResponseBuilder;

View File

@ -152,9 +152,10 @@ mod tests {
use actix_service::FnService;
use super::*;
use crate::dev::ServiceRequest;
use crate::http::header::CONTENT_TYPE;
use crate::test::{block_on, TestRequest};
use crate::{HttpResponse, ServiceRequest};
use crate::HttpResponse;
#[test]
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;
mod defaultheaders;
mod errhandlers;
mod logger;
pub use self::defaultheaders::DefaultHeaders;
pub use self::errhandlers::{ErrorHandlerResponse, ErrorHandlers};
pub use self::logger::Logger;
// #[cfg(feature = "session")]
// pub use actix_session as session;
mod logger;
pub use self::logger::Logger;
#[cfg(feature = "session")]
pub mod identity;

View File

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

View File

@ -17,8 +17,8 @@ type BoxedRouteService<Req, Res> = Box<
Service<
Request = Req,
Response = Res,
Error = (),
Future = Box<Future<Item = Res, Error = ()>>,
Error = Error,
Future = Box<Future<Item = Res, Error = Error>>,
>,
>;
@ -26,7 +26,7 @@ type BoxedRouteNewService<Req, Res> = Box<
NewService<
Request = Req,
Response = Res,
Error = (),
Error = Error,
InitError = (),
Service = BoxedRouteService<Req, Res>,
Future = Box<Future<Item = BoxedRouteService<Req, Res>, Error = ()>>,
@ -73,7 +73,7 @@ impl<P: 'static> Route<P> {
impl<P> NewService for Route<P> {
type Request = ServiceRequest<P>;
type Response = ServiceResponse;
type Error = ();
type Error = Error;
type InitError = ();
type Service = RouteService<P>;
type Future = CreateRouteService<P>;
@ -129,7 +129,7 @@ impl<P> RouteService<P> {
impl<P> Service for RouteService<P> {
type Request = ServiceRequest<P>;
type Response = ServiceResponse;
type Error = ();
type Error = Error;
type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
@ -188,7 +188,7 @@ impl<P: 'static> Route<P> {
// T: NewService<
// Request = HandlerRequest<S>,
// Response = HandlerRequest<S, U>,
// InitError = (),
// InitError = Error,
// >,
// {
// RouteServiceBuilder {
@ -372,7 +372,7 @@ where
{
type Request = ServiceRequest<P>;
type Response = ServiceResponse;
type Error = ();
type Error = Error;
type InitError = ();
type Service = BoxedRouteService<ServiceRequest<P>, Self::Response>;
type Future = Box<Future<Item = Self::Service, Error = Self::InitError>>;
@ -410,11 +410,11 @@ where
{
type Request = ServiceRequest<P>;
type Response = ServiceResponse;
type Error = ();
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().map_err(|_| ())
self.service.poll_ready().map_err(|(e, _)| e)
}
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 crate::dev::{HttpServiceFactory, ServiceConfig};
use crate::error::Error;
use crate::guard::Guard;
use crate::resource::Resource;
use crate::rmap::ResourceMap;
@ -20,9 +21,10 @@ use crate::service::{
};
type Guards = Vec<Box<Guard>>;
type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, ()>;
type HttpNewService<P> = BoxedNewService<(), ServiceRequest<P>, ServiceResponse, (), ()>;
type BoxedResponse = Box<Future<Item = ServiceResponse, Error = ()>>;
type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, Error>;
type HttpNewService<P> =
BoxedNewService<(), ServiceRequest<P>, ServiceResponse, Error, ()>;
type BoxedResponse = Box<Future<Item = ServiceResponse, Error = Error>>;
/// Resources scope
///
@ -83,7 +85,7 @@ where
T: NewService<
Request = ServiceRequest<P>,
Response = ServiceResponse,
Error = (),
Error = Error,
InitError = (),
>,
{
@ -176,7 +178,7 @@ where
U: NewService<
Request = ServiceRequest<P>,
Response = ServiceResponse,
Error = (),
Error = Error,
InitError = (),
> + 'static,
{
@ -201,7 +203,7 @@ where
impl NewService<
Request = ServiceRequest<P>,
Response = ServiceResponse,
Error = (),
Error = Error,
InitError = (),
>,
>
@ -210,7 +212,7 @@ where
T::Service,
Request = ServiceRequest<P>,
Response = ServiceResponse,
Error = (),
Error = Error,
InitError = (),
>,
F: IntoTransform<M, T::Service>,
@ -233,7 +235,7 @@ where
T: NewService<
Request = ServiceRequest<P>,
Response = ServiceResponse,
Error = (),
Error = Error,
InitError = (),
> + 'static,
{
@ -290,7 +292,7 @@ pub struct ScopeFactory<P> {
impl<P: 'static> NewService for ScopeFactory<P> {
type Request = ServiceRequest<P>;
type Response = ServiceResponse;
type Error = ();
type Error = Error;
type InitError = ();
type Service = ScopeService<P>;
type Future = ScopeFactoryResponse<P>;
@ -406,7 +408,7 @@ pub struct ScopeService<P> {
impl<P> Service for ScopeService<P> {
type Request = ServiceRequest<P>;
type Response = ServiceResponse;
type Error = ();
type Error = Error;
type Future = Either<BoxedResponse, FutureResult<Self::Response, 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> {
type Request = ServiceRequest<P>;
type Response = ServiceResponse;
type Error = ();
type Error = Error;
type InitError = ();
type Service = ScopeService<P>;
type Future = ScopeFactoryResponse<P>;

View File

@ -340,6 +340,12 @@ impl<B> ServiceResponse<B> {
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
#[inline]
pub fn request(&self) -> &HttpRequest {
@ -358,18 +364,6 @@ impl<B> ServiceResponse<B> {
&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.
pub fn checked_expr<F, E>(mut self, f: F) -> Self
where

View File

@ -14,9 +14,9 @@ use bytes::Bytes;
use futures::Future;
use crate::config::{AppConfig, AppConfigInner};
use crate::request::HttpRequest;
use crate::rmap::ResourceMap;
use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};
use crate::{HttpRequest, HttpResponse};
thread_local! {
static RT: RefCell<Runtime> = {
@ -277,6 +277,11 @@ impl TestRequest {
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
pub fn to_http_request(mut self) -> HttpRequest {
let req = self.req.finish();