rama_http_backend/client/proxy/layer/
proxy_address.rs1use rama_core::{
2 Context, Layer, Service,
3 error::{ErrorContext, OpaqueError},
4};
5use rama_net::address::ProxyAddress;
6use std::fmt;
7
8#[derive(Debug, Clone, Default)]
9pub struct HttpProxyAddressLayer {
18 address: Option<ProxyAddress>,
19 preserve: bool,
20}
21
22impl HttpProxyAddressLayer {
23 pub fn new(address: ProxyAddress) -> Self {
26 Self::maybe(Some(address))
27 }
28
29 pub fn maybe(address: Option<ProxyAddress>) -> Self {
33 Self {
34 address,
35 ..Default::default()
36 }
37 }
38
39 pub fn try_from_env_default() -> Result<Self, OpaqueError> {
42 Self::try_from_env("HTTP_PROXY")
43 }
44
45 pub fn try_from_env(key: impl AsRef<str>) -> Result<Self, OpaqueError> {
48 let env_result = std::env::var(key.as_ref()).ok();
49 let env_result_mapped = env_result.as_ref().and_then(|v| {
50 let v = v.trim();
51 if v.is_empty() { None } else { Some(v) }
52 });
53
54 let proxy_address = match env_result_mapped {
55 Some(value) => Some(value.try_into().context("parse std env proxy info")?),
56 None => None,
57 };
58
59 Ok(Self::maybe(proxy_address))
60 }
61
62 pub fn preserve(mut self, preserve: bool) -> Self {
64 self.preserve = preserve;
65 self
66 }
67
68 pub fn set_preserve(&mut self, preserve: bool) -> &mut Self {
70 self.preserve = preserve;
71 self
72 }
73}
74
75impl<S> Layer<S> for HttpProxyAddressLayer {
76 type Service = HttpProxyAddressService<S>;
77
78 fn layer(&self, inner: S) -> Self::Service {
79 HttpProxyAddressService::maybe(inner, self.address.clone()).preserve(self.preserve)
80 }
81
82 fn into_layer(self, inner: S) -> Self::Service {
83 HttpProxyAddressService::maybe(inner, self.address).preserve(self.preserve)
84 }
85}
86
87pub struct HttpProxyAddressService<S> {
94 inner: S,
95 address: Option<ProxyAddress>,
96 preserve: bool,
97}
98
99impl<S: fmt::Debug> fmt::Debug for HttpProxyAddressService<S> {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 f.debug_struct("HttpProxyAddressService")
102 .field("inner", &self.inner)
103 .field("address", &self.address)
104 .field("preserve", &self.preserve)
105 .finish()
106 }
107}
108
109impl<S: Clone> Clone for HttpProxyAddressService<S> {
110 fn clone(&self) -> Self {
111 Self {
112 inner: self.inner.clone(),
113 address: self.address.clone(),
114 preserve: self.preserve,
115 }
116 }
117}
118
119impl<S> HttpProxyAddressService<S> {
120 pub const fn new(inner: S, address: ProxyAddress) -> Self {
123 Self::maybe(inner, Some(address))
124 }
125
126 pub const fn maybe(inner: S, address: Option<ProxyAddress>) -> Self {
130 Self {
131 inner,
132 address,
133 preserve: false,
134 }
135 }
136
137 pub fn try_from_env_default(inner: S) -> Result<Self, OpaqueError> {
140 Self::try_from_env(inner, "HTTP_PROXY")
141 }
142
143 pub fn try_from_env(inner: S, key: impl AsRef<str>) -> Result<Self, OpaqueError> {
146 let env_result = std::env::var(key.as_ref()).ok();
147 let env_result_mapped = env_result.as_ref().and_then(|v| {
148 let v = v.trim();
149 if v.is_empty() { None } else { Some(v) }
150 });
151
152 let proxy_address = match env_result_mapped {
153 Some(value) => Some(value.try_into().context("parse std env proxy info")?),
154 None => None,
155 };
156
157 Ok(Self::maybe(inner, proxy_address))
158 }
159
160 pub const fn preserve(mut self, preserve: bool) -> Self {
162 self.preserve = preserve;
163 self
164 }
165
166 pub fn set_preserve(&mut self, preserve: bool) -> &mut Self {
168 self.preserve = preserve;
169 self
170 }
171}
172
173impl<S, State, Request> Service<State, Request> for HttpProxyAddressService<S>
174where
175 S: Service<State, Request>,
176 State: Clone + Send + Sync + 'static,
177{
178 type Response = S::Response;
179 type Error = S::Error;
180
181 fn serve(
182 &self,
183 mut ctx: Context<State>,
184 req: Request,
185 ) -> impl Future<Output = Result<Self::Response, Self::Error>> + Send + '_ {
186 if let Some(ref address) = self.address {
187 if !self.preserve || !ctx.contains::<ProxyAddress>() {
188 tracing::trace!(authority = %address.authority, "setting proxy address");
189 ctx.insert(address.clone());
190 }
191 }
192 self.inner.serve(ctx, req)
193 }
194}