satex_layer/remove_header/
remove_response_header.rs1use crate::make::MakeRouteLayer;
2use crate::remove_header::Removable;
3use http::HeaderName;
4use pin_project_lite::pin_project;
5use satex_core::component::Args;
6use satex_core::{component::Configurable, Error};
7use satex_macro::make;
8use std::pin::Pin;
9use std::task::{ready, Context, Poll};
10use std::{str::FromStr, sync::Arc};
11use tower::{Layer, Service};
12
13#[make(kind = RemoveResponseHeader)]
14pub struct MakeRemoveResponseHeaderRouteLayer {
15 name: String,
16}
17
18impl MakeRouteLayer for MakeRemoveResponseHeaderRouteLayer {
19 type Layer = RemoveResponseHeaderLayer;
20
21 fn make(&self, args: Args) -> Result<Self::Layer, Error> {
22 Config::with_args(args).and_then(|config| {
23 HeaderName::from_str(&config.name)
24 .map_err(Error::new)
25 .map(RemoveResponseHeaderLayer::new)
26 })
27 }
28}
29
30#[derive(Debug, Clone)]
31pub struct RemoveResponseHeaderLayer {
32 name: Arc<HeaderName>,
33}
34
35impl RemoveResponseHeaderLayer {
36 pub fn new(name: HeaderName) -> Self {
37 Self {
38 name: Arc::new(name),
39 }
40 }
41}
42
43impl<S> Layer<S> for RemoveResponseHeaderLayer {
44 type Service = RemoveResponseHeader<S>;
45
46 fn layer(&self, inner: S) -> Self::Service {
47 RemoveResponseHeader {
48 name: self.name.clone(),
49 inner,
50 }
51 }
52}
53
54#[derive(Debug, Clone)]
55pub struct RemoveResponseHeader<S> {
56 inner: S,
57 name: Arc<HeaderName>,
58}
59
60impl<S, Req, Res> Service<Req> for RemoveResponseHeader<S>
61where
62 S: Service<Req, Response=Res>,
63 Res: Removable,
64{
65 type Response = S::Response;
66
67 type Error = S::Error;
68
69 type Future = ResponseFuture<S::Future>;
70
71 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
72 self.inner.poll_ready(cx)
73 }
74
75 fn call(&mut self, request: Req) -> Self::Future {
76 let name = self.name.clone();
77 ResponseFuture::new(name, self.inner.call(request))
78 }
79}
80
81pin_project! {
82 #[project = ResponseFutureProj]
83 #[project_replace = ResponseFutureProjReplace]
84 pub enum ResponseFuture<F> {
85 Incomplete {
86 name: Arc<HeaderName>,
87 #[pin]
88 future: F,
89 },
90 Complete,
91 }
92}
93
94impl<F> ResponseFuture<F> {
95 pub fn new(name: Arc<HeaderName>, future: F) -> Self {
96 Self::Incomplete { name, future }
97 }
98}
99
100impl<F, Res, E> Future for ResponseFuture<F>
101where
102 F: Future<Output=Result<Res, E>>,
103 Res: Removable,
104{
105 type Output = F::Output;
106
107 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
108 match self.as_mut().project() {
109 ResponseFutureProj::Incomplete { future, .. } => match ready!(future.poll(cx)) {
110 Ok(mut res) => match self.project_replace(ResponseFuture::Complete) {
111 ResponseFutureProjReplace::Incomplete { name, .. } => {
112 res.remove(name.as_ref());
113 Poll::Ready(Ok(res))
114 }
115 ResponseFutureProjReplace::Complete => unreachable!(),
116 },
117 Err(e) => Poll::Ready(Err(e)),
118 },
119 ResponseFutureProj::Complete { .. } => {
120 panic!("polled after completion")
121 }
122 }
123 }
124}