rama_http/layer/
error_handling.rs1use crate::service::web::response::{ErrorResponse, IntoResponse};
50use crate::{Request, Response};
51use rama_core::{Layer, Service};
52use rama_utils::macros::define_inner_service_accessors;
53use std::convert::Infallible;
54
55#[derive(Debug, Clone)]
57pub struct ErrorHandlerLayer<F = ()> {
58 error_mapper: F,
59}
60
61impl Default for ErrorHandlerLayer {
62 fn default() -> Self {
63 Self::new()
64 }
65}
66
67impl ErrorHandlerLayer {
68 #[must_use]
70 pub const fn new() -> Self {
71 Self { error_mapper: () }
72 }
73
74 pub fn error_mapper<F>(self, error_mapper: F) -> ErrorHandlerLayer<F> {
79 ErrorHandlerLayer { error_mapper }
80 }
81}
82
83impl<S, F: Clone> Layer<S> for ErrorHandlerLayer<F> {
84 type Service = ErrorHandler<S, F>;
85
86 fn layer(&self, inner: S) -> Self::Service {
87 ErrorHandler::new(inner).error_mapper(self.error_mapper.clone())
88 }
89
90 fn into_layer(self, inner: S) -> Self::Service {
91 ErrorHandler::new(inner).error_mapper(self.error_mapper)
92 }
93}
94
95#[derive(Debug, Clone)]
97pub struct ErrorHandler<S, F = ()> {
98 inner: S,
99 error_mapper: F,
100}
101
102impl<S> ErrorHandler<S> {
103 pub const fn new(inner: S) -> Self {
105 Self {
106 inner,
107 error_mapper: (),
108 }
109 }
110
111 define_inner_service_accessors!();
112
113 pub fn error_mapper<F>(self, error_mapper: F) -> ErrorHandler<S, F> {
118 ErrorHandler {
119 inner: self.inner,
120 error_mapper,
121 }
122 }
123}
124
125impl<S, Body> Service<Request<Body>> for ErrorHandler<S, ()>
126where
127 S: Service<Request<Body>, Output: IntoResponse, Error: Into<ErrorResponse>>,
128 Body: Send + 'static,
129{
130 type Output = Response;
131 type Error = Infallible;
132
133 async fn serve(&self, req: Request<Body>) -> Result<Self::Output, Self::Error> {
134 match self.inner.serve(req).await {
135 Ok(response) => Ok(response.into_response()),
136 Err(error) => Ok(error.into().into_response()),
137 }
138 }
139}
140
141impl<S, F, R, Body> Service<Request<Body>> for ErrorHandler<S, F>
142where
143 S: Service<Request<Body>, Output: IntoResponse>,
144 F: Fn(S::Error) -> R + Clone + Send + Sync + 'static,
145 R: IntoResponse + 'static,
146 Body: Send + 'static,
147{
148 type Output = Response;
149 type Error = Infallible;
150
151 async fn serve(&self, req: Request<Body>) -> Result<Self::Output, Self::Error> {
152 match self.inner.serve(req).await {
153 Ok(response) => Ok(response.into_response()),
154 Err(error) => Ok((self.error_mapper)(error).into_response()),
155 }
156 }
157}