-
-
Notifications
You must be signed in to change notification settings - Fork 332
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
SetBaseUriLayer
to set base URI of requests
- Loading branch information
Showing
6 changed files
with
117 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
//! Set base URI of requests. | ||
use http::{uri, Request}; | ||
use tower::{Layer, Service}; | ||
|
||
/// Layer that applies [`SetBaseUri`] which makes all requests relative to the base URI. | ||
/// | ||
/// Path in `base_uri` is preseved. | ||
#[derive(Debug, Clone)] | ||
pub struct SetBaseUriLayer { | ||
base_uri: http::Uri, | ||
} | ||
|
||
impl SetBaseUriLayer { | ||
/// Set base URI of requests. | ||
pub fn new(base_uri: http::Uri) -> Self { | ||
Self { base_uri } | ||
} | ||
} | ||
|
||
impl<S> Layer<S> for SetBaseUriLayer { | ||
type Service = SetBaseUri<S>; | ||
|
||
fn layer(&self, inner: S) -> Self::Service { | ||
SetBaseUri { | ||
base_uri: self.base_uri.clone(), | ||
inner, | ||
} | ||
} | ||
} | ||
|
||
/// Middleware that sets base URI so that all requests are relative to it. | ||
#[derive(Debug, Clone)] | ||
pub struct SetBaseUri<S> { | ||
base_uri: http::Uri, | ||
inner: S, | ||
} | ||
|
||
impl<S, ReqBody> Service<Request<ReqBody>> for SetBaseUri<S> | ||
where | ||
S: Service<Request<ReqBody>>, | ||
{ | ||
type Error = S::Error; | ||
type Future = S::Future; | ||
type Response = S::Response; | ||
|
||
fn poll_ready(&mut self, cx: &mut std::task::Context<'_>) -> std::task::Poll<Result<(), Self::Error>> { | ||
self.inner.poll_ready(cx) | ||
} | ||
|
||
fn call(&mut self, req: Request<ReqBody>) -> Self::Future { | ||
let (mut parts, body) = req.into_parts(); | ||
let req_pandq = parts.uri.path_and_query(); | ||
parts.uri = set_base_uri(&self.base_uri, req_pandq); | ||
self.inner.call(Request::from_parts(parts, body)) | ||
} | ||
} | ||
|
||
// Join base URI and Path+Query, preserving any path in the base. | ||
fn set_base_uri(base_uri: &http::Uri, req_pandq: Option<&uri::PathAndQuery>) -> http::Uri { | ||
let mut builder = uri::Builder::new(); | ||
if let Some(scheme) = base_uri.scheme() { | ||
builder = builder.scheme(scheme.as_str()); | ||
} | ||
if let Some(authority) = base_uri.authority() { | ||
builder = builder.authority(authority.as_str()); | ||
} | ||
|
||
if let Some(pandq) = base_uri.path_and_query() { | ||
builder = if let Some(req_pandq) = req_pandq { | ||
// Remove any trailing slashes and join. | ||
// `PathAndQuery` always starts with a slash. | ||
let base_path = pandq.path().trim_end_matches('/'); | ||
builder.path_and_query(format!("{}{}", base_path, req_pandq)) | ||
} else { | ||
builder.path_and_query(pandq.as_str()) | ||
}; | ||
} else if let Some(req_pandq) = req_pandq { | ||
builder = builder.path_and_query(req_pandq.as_str()); | ||
} | ||
|
||
// Joining a valid Uri and valid PathAndQuery should result in a valid Uri. | ||
builder.build().expect("Valid Uri") | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
#[test] | ||
fn normal_host() { | ||
let base_uri = http::Uri::from_static("https://192.168.1.65:8443"); | ||
let apipath = http::Uri::from_static("/api/v1/nodes?hi=yes"); | ||
let pandq = apipath.path_and_query(); | ||
assert_eq!( | ||
super::set_base_uri(&base_uri, pandq), | ||
"https://192.168.1.65:8443/api/v1/nodes?hi=yes" | ||
); | ||
} | ||
|
||
#[test] | ||
fn rancher_host() { | ||
// in rancher, kubernetes server names are not hostnames, but a host with a path: | ||
let base_uri = http::Uri::from_static("https://example.com/foo/bar"); | ||
let api_path = http::Uri::from_static("/api/v1/nodes?hi=yes"); | ||
let pandq = api_path.path_and_query(); | ||
assert_eq!( | ||
super::set_base_uri(&base_uri, pandq), | ||
"https://example.com/foo/bar/api/v1/nodes?hi=yes" | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,16 @@ | ||
//! Abstracts the connection to Kubernetes API server. | ||
//! Middleware for customizing client. | ||
mod auth; | ||
mod base_uri; | ||
#[cfg(feature = "gzip")] mod compression; | ||
mod headers; | ||
mod log; | ||
mod url; | ||
|
||
#[cfg(feature = "gzip")] | ||
pub(crate) use self::compression::{accept_compressed, maybe_decompress}; | ||
pub use self::url::set_cluster_url; | ||
pub(crate) use self::{ | ||
auth::{AuthLayer, Authentication}, | ||
headers::set_default_headers, | ||
log::LogRequest, | ||
}; | ||
pub use base_uri::{SetBaseUri, SetBaseUriLayer}; |
This file was deleted.
Oops, something went wrong.