gateway_runtime/layers/
error.rs1use crate::alloc::boxed::Box;
10use crate::gateway::ErrorHandler;
11use crate::{GatewayError, GatewayRequest, GatewayResponse};
12use core::task::{Context, Poll};
13use std::future::Future;
14use std::pin::Pin;
15use tower::Service;
16
17#[derive(Clone)]
19pub struct ErrorLayer<S> {
20 inner: S,
21 handler: Option<ErrorHandler>,
22}
23
24impl<S> ErrorLayer<S> {
25 pub fn new(inner: S, handler: Option<ErrorHandler>) -> Self {
31 Self { inner, handler }
32 }
33}
34
35impl<S> Service<GatewayRequest> for ErrorLayer<S>
36where
37 S: Service<GatewayRequest, Response = GatewayResponse, Error = GatewayError>,
38 S::Future: Send + 'static,
39{
40 type Response = GatewayResponse;
41 type Error = GatewayError;
42 type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
43
44 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
45 self.inner.poll_ready(cx)
46 }
47
48 fn call(&mut self, req: GatewayRequest) -> Self::Future {
49 let method = req.method().clone();
52 let uri = req.uri().clone();
53 let headers = req.headers().clone();
54
55 let handler_clone = self.handler.clone();
56
57 let fut = self.inner.call(req);
58
59 Box::pin(async move {
60 match fut.await {
61 Ok(resp) => Ok(resp),
62 Err(err) => {
63 if let Some(h) = handler_clone {
64 let mut partial_req = http::Request::builder()
67 .method(method)
68 .uri(uri)
69 .body(crate::alloc::vec::Vec::new())
70 .unwrap();
71 *partial_req.headers_mut() = headers;
72
73 Ok(h(&partial_req, err))
75 } else {
76 Err(err)
78 }
79 }
80 }
81 })
82 }
83}