kube_client/client/middleware/
base_uri.rs1use http::{uri, Request};
3use tower::{Layer, Service};
4
5#[derive(Debug, Clone)]
9pub struct BaseUriLayer {
10 base_uri: http::Uri,
11}
12
13impl BaseUriLayer {
14 pub fn new(base_uri: http::Uri) -> Self {
16 Self { base_uri }
17 }
18}
19
20impl<S> Layer<S> for BaseUriLayer {
21 type Service = BaseUri<S>;
22
23 fn layer(&self, inner: S) -> Self::Service {
24 BaseUri {
25 base_uri: self.base_uri.clone(),
26 inner,
27 }
28 }
29}
30
31#[derive(Debug, Clone)]
33pub struct BaseUri<S> {
34 base_uri: http::Uri,
35 inner: S,
36}
37
38impl<S, ReqBody> Service<Request<ReqBody>> for BaseUri<S>
39where
40 S: Service<Request<ReqBody>>,
41{
42 type Error = S::Error;
43 type Future = S::Future;
44 type Response = S::Response;
45
46 fn poll_ready(&mut self, cx: &mut std::task::Context<'_>) -> std::task::Poll<Result<(), Self::Error>> {
47 self.inner.poll_ready(cx)
48 }
49
50 fn call(&mut self, req: Request<ReqBody>) -> Self::Future {
51 let (mut parts, body) = req.into_parts();
52 let req_pandq = parts.uri.path_and_query();
53 parts.uri = set_base_uri(&self.base_uri, req_pandq);
54 self.inner.call(Request::from_parts(parts, body))
55 }
56}
57
58fn set_base_uri(base_uri: &http::Uri, req_pandq: Option<&uri::PathAndQuery>) -> http::Uri {
60 let mut builder = uri::Builder::new();
61 if let Some(scheme) = base_uri.scheme() {
62 builder = builder.scheme(scheme.as_str());
63 }
64 if let Some(authority) = base_uri.authority() {
65 builder = builder.authority(authority.as_str());
66 }
67
68 if let Some(pandq) = base_uri.path_and_query() {
69 builder = if let Some(req_pandq) = req_pandq {
70 let base_path = pandq.path().trim_end_matches('/');
73 builder.path_and_query(format!("{base_path}{req_pandq}"))
74 } else {
75 builder.path_and_query(pandq.as_str())
76 };
77 } else if let Some(req_pandq) = req_pandq {
78 builder = builder.path_and_query(req_pandq.as_str());
79 }
80
81 builder.build().expect("Valid Uri")
83}
84
85#[cfg(test)]
86mod tests {
87 #[test]
88 fn normal_host() {
89 let base_uri = http::Uri::from_static("https://192.168.1.65:8443");
90 let apipath = http::Uri::from_static("/api/v1/nodes?hi=yes");
91 let pandq = apipath.path_and_query();
92 assert_eq!(
93 super::set_base_uri(&base_uri, pandq),
94 "https://192.168.1.65:8443/api/v1/nodes?hi=yes"
95 );
96 }
97
98 #[test]
99 fn rancher_host() {
100 let base_uri = http::Uri::from_static("https://example.com/foo/bar");
102 let api_path = http::Uri::from_static("/api/v1/nodes?hi=yes");
103 let pandq = api_path.path_and_query();
104 assert_eq!(
105 super::set_base_uri(&base_uri, pandq),
106 "https://example.com/foo/bar/api/v1/nodes?hi=yes"
107 );
108 }
109}