rama_http_backend/client/proxy/layer/
proxy_auth_header.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use rama_core::{Context, Layer, Service};
use rama_http_types::{
    headers::{HeaderMapExt, ProxyAuthorization},
    Request,
};
use rama_net::{address::ProxyAddress, http::RequestContext, user::ProxyCredential};
use std::{fmt, future::Future};

#[derive(Debug, Clone, Default)]
#[non_exhaustive]
/// A [`Layer`] which will set the http auth header
/// in case there is a [`ProxyAddress`] in the [`Context`].
pub struct SetProxyAuthHttpHeaderLayer;

impl SetProxyAuthHttpHeaderLayer {
    /// Create a new [`SetProxyAuthHttpHeaderLayer`].
    pub fn new() -> Self {
        Self::default()
    }
}

impl<S> Layer<S> for SetProxyAuthHttpHeaderLayer {
    type Service = SetProxyAuthHttpHeaderService<S>;

    fn layer(&self, inner: S) -> Self::Service {
        SetProxyAuthHttpHeaderService::new(inner)
    }
}

/// A [`Service`] wwhich will set the http auth header
/// in case there is a [`ProxyAddress`] in the [`Context`].
pub struct SetProxyAuthHttpHeaderService<S> {
    inner: S,
}

impl<S: fmt::Debug> fmt::Debug for SetProxyAuthHttpHeaderService<S> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("SetProxyAuthHttpHeaderService")
            .field("inner", &self.inner)
            .finish()
    }
}

impl<S: Clone> Clone for SetProxyAuthHttpHeaderService<S> {
    fn clone(&self) -> Self {
        Self {
            inner: self.inner.clone(),
        }
    }
}

impl<S> SetProxyAuthHttpHeaderService<S> {
    /// Create a new [`SetProxyAuthHttpHeaderService`].
    pub const fn new(inner: S) -> Self {
        Self { inner }
    }
}

impl<S, State, Body> Service<State, Request<Body>> for SetProxyAuthHttpHeaderService<S>
where
    S: Service<State, Request<Body>>,
    State: Clone + Send + Sync + 'static,
    Body: Send + 'static,
{
    type Response = S::Response;
    type Error = S::Error;

    fn serve(
        &self,
        mut ctx: Context<State>,
        mut req: Request<Body>,
    ) -> impl Future<Output = Result<Self::Response, Self::Error>> + Send + '_ {
        let maybe_request_ctx = ctx
            .get_or_try_insert_with_ctx::<RequestContext, _>(|ctx| (ctx, &req).try_into())
            .ok();
        if !maybe_request_ctx
            .map(|ctx| ctx.protocol.is_secure())
            .unwrap_or_default()
        {
            // only do this for non-secure requests!!!

            if let Some(pa) = ctx.get::<ProxyAddress>() {
                if let Some(credential) = pa.credential.clone() {
                    match credential {
                        ProxyCredential::Basic(basic) => {
                            tracing::trace!("inserted proxy Basic credentials into (http) request");
                            req.headers_mut().typed_insert(ProxyAuthorization(basic))
                        }
                        ProxyCredential::Bearer(bearer) => {
                            tracing::trace!(
                                "inserted proxy Bearer credentials into (http) request"
                            );
                            req.headers_mut().typed_insert(ProxyAuthorization(bearer))
                        }
                    }
                }
            }
        }

        self.inner.serve(ctx, req)
    }
}