diff --git a/actix-web/src/response/response.rs b/actix-web/src/response/response.rs index e16dc0cd911..26df8cb3cc0 100644 --- a/actix-web/src/response/response.rs +++ b/actix-web/src/response/response.rs @@ -8,6 +8,7 @@ use actix_http::{ header::HeaderMap, Extensions, Response, ResponseHead, StatusCode, }; +use bytes::Bytes; #[cfg(feature = "cookies")] use { actix_http::{ @@ -79,6 +80,12 @@ impl HttpResponse { self.error.as_ref() } + /// Retrieve the source `error` for this response, leaving a `None` in its place. + #[inline] + pub fn take_error(&mut self) -> Option { + self.error.take() + } + /// Get the response status code #[inline] pub fn status(&self) -> StatusCode { @@ -319,6 +326,78 @@ impl From for HttpResponse { } } +impl From<&'static str> for HttpResponse<&'static str> { + fn from(val: &'static str) -> Self { + HttpResponse { + res: Response::from(val), + error: None, + } + } +} + +impl From<&'static [u8]> for HttpResponse<&'static [u8]> { + fn from(val: &'static [u8]) -> Self { + HttpResponse { + res: Response::from(val), + error: None, + } + } +} + +impl From for HttpResponse { + fn from(val: String) -> Self { + HttpResponse { + res: Response::from(val), + error: None, + } + } +} + +impl From<&String> for HttpResponse { + fn from(val: &String) -> Self { + HttpResponse { + res: Response::from(val), + error: None, + } + } +} + +impl From> for HttpResponse> { + fn from(val: Vec) -> Self { + HttpResponse { + res: Response::from(val), + error: None, + } + } +} + +impl From<&Vec> for HttpResponse> { + fn from(val: &Vec) -> Self { + HttpResponse { + res: Response::from(val), + error: None, + } + } +} + +impl From for HttpResponse { + fn from(val: Bytes) -> Self { + HttpResponse { + res: Response::from(val), + error: None, + } + } +} + +impl From for HttpResponse { + fn from(val: bytestring::ByteString) -> Self { + HttpResponse { + res: Response::from(val), + error: None, + } + } +} + impl From> for Response { fn from(res: HttpResponse) -> Self { // this impl will always be called as part of dispatcher @@ -415,6 +494,17 @@ mod tests { let dbg = format!("{:?}", resp); assert!(dbg.contains("HttpResponse")); } + + #[test] + fn test_take_error() { + let err = crate::error::ErrorBadRequest("error"); + let mut resp = HttpResponse::from_error(err); + assert!(resp.error().is_some()); + + let err = resp.take_error(); + assert!(err.is_some()); + assert!(resp.error().is_none()); + } } #[cfg(test)] diff --git a/actix-web/src/service.rs b/actix-web/src/service.rs index 812879864b2..9f173ece45a 100644 --- a/actix-web/src/service.rs +++ b/actix-web/src/service.rs @@ -153,9 +153,8 @@ impl ServiceRequest { /// Create `ServiceResponse` from this request and given response. #[inline] - pub fn into_response>>(self, res: R) -> ServiceResponse { - let res = HttpResponse::from(res.into()); - ServiceResponse::new(self.req, res) + pub fn into_response>>(self, res: R) -> ServiceResponse { + ServiceResponse::new(self.req, res.into()) } /// Create `ServiceResponse` from this request and given error. @@ -463,6 +462,12 @@ impl ServiceResponse { &mut self.response } + /// Retrieve the source `error` for this response, leaving a `None` in its place. + #[inline] + pub fn take_error(&mut self) -> Option { + self.response.take_error() + } + /// Returns response status code. #[inline] pub fn status(&self) -> StatusCode { @@ -803,6 +808,17 @@ mod tests { assert!(s.contains("x-test")); } + #[test] + fn test_take_error() { + let res = HttpResponse::from_error(crate::error::ErrorBadRequest("error")); + let mut res = TestRequest::default().to_srv_response(res); + assert!(res.response().error().is_some()); + + let err = res.take_error(); + assert!(err.is_some()); + assert!(res.response().error().is_none()); + } + #[actix_rt::test] async fn test_services_macro() { let scoped = services![