use reqwest::Client;
use url::Url;
use uuid::Uuid;
use super::error::ApiError;
use super::ApiRequest;
use crate::http_server::api::v0::bucket::list::{ListRequest, ListResponse};
#[derive(Debug, Clone)]
pub struct ApiClient {
pub remote: Url,
client: Client,
}
impl ApiClient {
pub fn new(remote: &Url) -> Result<Self, ApiError> {
let client = Client::builder().build()?;
Ok(Self {
remote: remote.clone(),
client,
})
}
pub async fn call<T: ApiRequest>(&mut self, request: T) -> Result<T::Response, ApiError> {
let request_builder = request.build_request(&self.remote, &self.client);
let response = request_builder.send().await?;
if response.status().is_success() {
Ok(response.json::<T::Response>().await?)
} else {
Err(ApiError::HttpStatus(
response.status(),
response.text().await?,
))
}
}
pub async fn resolve_bucket_name(&mut self, name: &str) -> Result<Uuid, ApiError> {
let request = ListRequest {
prefix: Some(name.to_string()),
limit: Some(100),
status: None,
};
let response: ListResponse = self.call(request).await?;
response
.buckets
.into_iter()
.find(|b| b.name == name)
.map(|b| b.bucket_id)
.ok_or_else(|| {
ApiError::HttpStatus(
reqwest::StatusCode::NOT_FOUND,
format!("Bucket not found: {}", name),
)
})
}
pub fn base_url(&self) -> &Url {
&self.remote
}
pub fn http_client(&self) -> &Client {
&self.client
}
}
pub async fn resolve_bucket(client: &mut ApiClient, identifier: &str) -> Result<Uuid, ApiError> {
if let Ok(uuid) = Uuid::parse_str(identifier) {
return Ok(uuid);
}
client.resolve_bucket_name(identifier).await
}