Skip to content

Instantly share code, notes, and snippets.

@grampelberg
Last active June 24, 2024 20:42
Show Gist options
  • Save grampelberg/5f85bada575bd5654f3458e556a7a14a to your computer and use it in GitHub Desktop.
Save grampelberg/5f85bada575bd5654f3458e556a7a14a to your computer and use it in GitHub Desktop.
#[derive(Debug, Clone)]
pub struct Client {
service_url: url::Url,
}
impl Client {
pub fn new(service_url: &str) -> Result<Self, Report> {
let url = url::Url::parse(service_url)?;
Ok(Self { service_url: url })
}
async fn _get<T>(&self, segments: Vec<&str>) -> Result<T, Report>
where
T: Request + DeserializeOwned + Into<T>,
{
let url = segments
.iter()
.try_fold(self.service_url.clone(), |a, b| a.join(b))?;
Ok(reqwest::get(url).await?.json::<T::Response>().await?.into())
}
pub async fn list<T>(&self) -> Result<T, Report>
where
T: Request + DeserializeOwned,
{
self._get(vec![T::url()]).await
}
pub async fn get<T>(&self, name: &str) -> Result<T, Report>
where
T: Request + DeserializeOwned,
{
self._get(vec![T::url(), name]).await
}
}
impl From<ListNamespacesResponse> for Vec<DataNamespace> {
fn from(resp: ListNamespacesResponse) -> Self {
resp.namespaces
}
}
impl Request for Vec<DataNamespace> {
type Response = ListNamespacesResponse;
fn url() -> &'static str {
<DataNamespace as Request>::url()
}
}
impl From<GetNamespaceResponse> for DataNamespace {
fn from(resp: GetNamespaceResponse) -> Self {
resp.namespace
}
}
impl Request for DataNamespace {
type Response = GetNamespaceResponse;
fn url() -> &'static str {
"namespaces"
}
}
pub trait Request: Sized {
type Response: DeserializeOwned + Into<Self>;
fn url() -> &'static str;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment