service/http_server/api/v0/bucket/
list.rs1use axum::extract::{Json, State};
2use axum::response::{IntoResponse, Response};
3use reqwest::{Client, RequestBuilder, Url};
4use serde::{Deserialize, Serialize};
5use time::OffsetDateTime;
6use uuid::Uuid;
7
8use common::prelude::Link;
9
10use crate::http_server::api::client::ApiRequest;
11use crate::ServiceState;
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
14#[cfg_attr(feature = "clap", derive(clap::Args))]
15pub struct ListRequest {
16 #[serde(skip_serializing_if = "Option::is_none")]
18 #[cfg_attr(feature = "clap", arg(long))]
19 pub prefix: Option<String>,
20
21 #[serde(skip_serializing_if = "Option::is_none")]
23 #[cfg_attr(feature = "clap", arg(long))]
24 pub limit: Option<u32>,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct ListResponse {
29 pub buckets: Vec<BucketInfo>,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct BucketInfo {
34 pub bucket_id: Uuid,
35 pub name: String,
36 pub link: Link,
37 #[serde(with = "time::serde::rfc3339")]
38 pub created_at: OffsetDateTime,
39}
40
41pub async fn handler(
42 State(state): State<ServiceState>,
43 Json(_req): Json<ListRequest>,
44) -> Result<impl IntoResponse, ListError> {
45 let buckets = crate::mount_ops::list_buckets(&state)
47 .await
48 .map_err(|e| ListError::MountOps(e.to_string()))?;
49
50 let bucket_infos = buckets
52 .into_iter()
53 .map(|b| BucketInfo {
54 bucket_id: b.bucket_id,
55 name: b.name,
56 link: b.link,
57 created_at: b.created_at,
58 })
59 .collect();
60
61 Ok((
62 http::StatusCode::OK,
63 Json(ListResponse {
64 buckets: bucket_infos,
65 }),
66 )
67 .into_response())
68}
69
70#[derive(Debug, thiserror::Error)]
71pub enum ListError {
72 #[error("MountOps error: {0}")]
73 MountOps(String),
74}
75
76impl IntoResponse for ListError {
77 fn into_response(self) -> Response {
78 match self {
79 ListError::MountOps(_) => (
80 http::StatusCode::INTERNAL_SERVER_ERROR,
81 "unknown server error",
82 )
83 .into_response(),
84 }
85 }
86}
87
88impl ApiRequest for ListRequest {
90 type Response = ListResponse;
91
92 fn build_request(self, base_url: &Url, client: &Client) -> RequestBuilder {
93 let full_url = base_url.join("/api/v0/bucket/list").unwrap();
94 client.post(full_url).json(&self)
95 }
96}