1use super::Client;
2use super::sign_v4::HTTPVerb;
3use super::utils::{get_request_header, parse_xml_response};
4use crate::oss::Error;
5use bon::Builder;
6use serde::{Deserialize, Serialize};
7use serde_with::{DisplayFromStr, serde_as};
8use std::collections::HashMap;
9use url::Url;
10
11#[serde_as]
12#[serde_with::skip_serializing_none]
13#[derive(Builder, Serialize)]
14#[serde(rename_all = "kebab-case")]
15pub struct ListBuckets<'a> {
16 #[builder(start_fn)]
17 #[serde(skip_serializing)]
18 pub(crate) client: &'a Client,
19 #[serde(skip_serializing)]
21 pub(crate) x_oss_resource_group_id: Option<&'a str>,
22 pub(crate) prefix: Option<&'a str>,
24 pub(crate) marker: Option<&'a str>,
25 #[serde_as(as = "Option<DisplayFromStr>")]
26 pub(crate) max_keys: Option<u16>,
27}
28
29#[derive(Deserialize, Debug)]
32#[serde(rename_all = "PascalCase")]
33pub struct ListAllMyBucketsResult {
34 pub prefix: Option<String>,
35 pub marker: Option<String>,
36 pub max_keys: Option<u32>,
37 pub is_truncated: Option<bool>,
38 pub next_marker: Option<String>,
39 pub owner: Owner,
40 #[serde(deserialize_with = "unwrap_buckets")]
42 pub buckets: Vec<Bucket>,
43}
44
45#[derive(Deserialize, Debug)]
46#[serde(rename_all = "PascalCase")]
47struct Buckets {
48 #[serde(default)]
49 bucket: Vec<Bucket>,
51}
52
53fn unwrap_buckets<'de, D>(deserializer: D) -> Result<Vec<Bucket>, D::Error>
54where
55 D: serde::Deserializer<'de>,
56{
57 let helper = Buckets::deserialize(deserializer)?;
58 Ok(helper.bucket)
59}
60
61#[derive(Deserialize, Debug)]
62#[serde(rename_all = "PascalCase")]
63pub struct Owner {
64 #[serde(rename = "ID")]
65 pub id: String,
66 pub display_name: String,
67}
68
69#[derive(Deserialize, Debug)]
70#[serde(rename_all = "PascalCase")]
71pub struct Bucket {
72 pub name: String,
73 pub creation_date: String,
74 pub location: String,
75 pub extranet_endpoint: String,
76 pub intranet_endpoint: String,
77 pub region: String,
78 pub storage_class: String,
79 pub resource_group_id: Option<String>,
80}
81impl ListBuckets<'_> {
84 pub async fn send(&self) -> Result<ListAllMyBucketsResult, Error> {
85 let query_map: HashMap<String, String> =
87 serde_json::from_value(serde_json::to_value(self).unwrap()).unwrap();
88
89 let client = self.client;
90 let request_url =
93 Url::parse_with_params(&format!("https://{}", client.endpoint), query_map).unwrap();
94
95 let mut request_header_map = HashMap::new();
96 if let Some(s) = self.x_oss_resource_group_id {
97 request_header_map.insert("x-oss-resource-group-id".to_owned(), s.to_owned());
98 }
99
100 let creds = client.credentials_provider.load().await?;
101 if let Some(token) = &creds.sts_security_token {
102 request_header_map.insert("x-oss-security-token".to_string(), token.clone());
103 }
104
105 let header_map = get_request_header(
106 &creds.access_key_id,
107 &creds.access_key_secret,
108 request_header_map,
109 &request_url,
110 HTTPVerb::Get,
111 &client.region,
112 None,
113 );
114
115 let resp = client
116 .http_client
117 .get(request_url)
118 .headers(header_map)
119 .send()
120 .await?;
121
122 let res = parse_xml_response(resp).await?;
123 Ok(res)
124 }
125}
126
127impl Client {
128 pub fn list_buckets(&self) -> ListBucketsBuilder<'_> {
129 ListBuckets::builder(self)
130 }
131}