Skip to main content

jax_daemon/http_server/api/client/
client.rs

1use reqwest::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 client = Client::builder().build()?;
18
19        Ok(Self {
20            remote: remote.clone(),
21            client,
22        })
23    }
24
25    pub async fn call<T: ApiRequest>(&mut self, request: T) -> Result<T::Response, ApiError> {
26        let request_builder = request.build_request(&self.remote, &self.client);
27        let response = request_builder.send().await?;
28
29        if response.status().is_success() {
30            Ok(response.json::<T::Response>().await?)
31        } else {
32            Err(ApiError::HttpStatus(
33                response.status(),
34                response.text().await?,
35            ))
36        }
37    }
38
39    /// Resolve a bucket name to a UUID
40    /// Returns the first bucket with an exact name match
41    pub async fn resolve_bucket_name(&mut self, name: &str) -> Result<Uuid, ApiError> {
42        let request = ListRequest {
43            prefix: Some(name.to_string()),
44            limit: Some(100),
45        };
46
47        let response: ListResponse = self.call(request).await?;
48
49        response
50            .buckets
51            .into_iter()
52            .find(|b| b.name == name)
53            .map(|b| b.bucket_id)
54            .ok_or_else(|| {
55                ApiError::HttpStatus(
56                    reqwest::StatusCode::NOT_FOUND,
57                    format!("Bucket not found: {}", name),
58                )
59            })
60    }
61
62    /// Get the base URL for API requests
63    pub fn base_url(&self) -> &Url {
64        &self.remote
65    }
66
67    /// Get the underlying HTTP client for custom requests
68    pub fn http_client(&self) -> &Client {
69        &self.client
70    }
71}
72
73/// Resolve a bucket identifier (name or UUID string) to a UUID.
74///
75/// Tries to parse as UUID first; if that fails, resolves by name via the API.
76pub async fn resolve_bucket(client: &mut ApiClient, identifier: &str) -> Result<Uuid, ApiError> {
77    if let Ok(uuid) = Uuid::parse_str(identifier) {
78        return Ok(uuid);
79    }
80    client.resolve_bucket_name(identifier).await
81}