service/http_server/api/client/
client.rs1use reqwest::{header::HeaderMap, header::HeaderValue, Client};
2use url::Url;
3use uuid::Uuid;
4
5use super::error::ApiError;
6use super::ApiRequest;
7use crate::http_server::api::v0::bucket::list::{ListRequest, ListResponse};
8
9#[derive(Debug, Clone)]
10pub struct ApiClient {
11 pub remote: Url,
12 client: Client,
13}
14
15impl ApiClient {
16 pub fn new(remote: &Url) -> Result<Self, ApiError> {
17 let mut default_headers = HeaderMap::new();
18 default_headers.insert("Content-Type", HeaderValue::from_static("application/json"));
19 let client = Client::builder().default_headers(default_headers).build()?;
20
21 Ok(Self {
22 remote: remote.clone(),
23 client,
24 })
25 }
26
27 pub async fn call<T: ApiRequest>(&mut self, request: T) -> Result<T::Response, ApiError> {
28 let request_builder = request.build_request(&self.remote, &self.client);
29 let response = request_builder.send().await?;
30
31 if response.status().is_success() {
32 Ok(response.json::<T::Response>().await?)
33 } else {
34 Err(ApiError::HttpStatus(
35 response.status(),
36 response.text().await?,
37 ))
38 }
39 }
40
41 pub async fn resolve_bucket_name(&mut self, name: &str) -> Result<Uuid, ApiError> {
44 let request = ListRequest {
45 prefix: Some(name.to_string()),
46 limit: Some(100),
47 };
48
49 let response: ListResponse = self.call(request).await?;
50
51 response
52 .buckets
53 .into_iter()
54 .find(|b| b.name == name)
55 .map(|b| b.bucket_id)
56 .ok_or_else(|| {
57 ApiError::HttpStatus(
58 reqwest::StatusCode::NOT_FOUND,
59 format!("Bucket not found: {}", name),
60 )
61 })
62 }
63
64 pub fn base_url(&self) -> &Url {
66 &self.remote
67 }
68
69 pub fn http_client(&self) -> &Client {
71 &self.client
72 }
73}