1use reqwest::header::{HeaderMap, DATE};
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5use crate::prelude::Owner;
6
7use super::auth::*;
8use super::errors::Error;
9use super::oss::OSS;
10
11#[derive(Clone, Debug, Serialize, Deserialize)]
12#[serde(rename_all = "PascalCase")]
13pub struct ListBuckets {
14 #[serde(default)]
15 prefix: String,
16 #[serde(default)]
17 marker: String,
18 #[serde(default)]
19 max_keys: String,
20 #[serde(default)]
21 is_truncated: bool,
22 #[serde(default)]
23 next_marker: String,
24
25 owner: Owner,
26
27 #[serde(default)]
28 buckets: Vec<Bucket>,
29}
30
31impl ListBuckets {
32 pub fn new(
33 prefix: String,
34 marker: String,
35 max_keys: String,
36 is_truncated: bool,
37 next_marker: String,
38 owner: Owner,
39 buckets: Vec<Bucket>,
40 ) -> Self {
41 ListBuckets {
42 prefix,
43 marker,
44 max_keys,
45 is_truncated,
46 next_marker,
47 owner,
48 buckets,
49 }
50 }
51
52 pub fn prefix(&self) -> &str {
53 &self.prefix
54 }
55
56 pub fn marker(&self) -> &str {
57 &self.marker
58 }
59
60 pub fn max_keys(&self) -> &str {
61 &self.max_keys
62 }
63
64 pub fn is_truncated(&self) -> bool {
65 self.is_truncated
66 }
67
68 pub fn next_marker(&self) -> &str {
69 &self.next_marker
70 }
71
72 pub fn id(&self) -> &str {
73 &self.owner.id
74 }
75
76 pub fn display_name(&self) -> &str {
77 &self.owner.display_name
78 }
79
80 pub fn buckets(&self) -> &Vec<Bucket> {
81 &self.buckets
82 }
83}
84
85#[derive(Clone, Debug, Serialize, Deserialize)]
86#[serde(rename_all = "PascalCase")]
87pub struct Bucket {
88 #[serde(default)]
89 name: String,
90 #[serde(default)]
91 creation_date: String,
92 #[serde(default)]
93 location: String,
94 #[serde(default)]
95 extranet_endpoint: String,
96 #[serde(default)]
97 intranet_endpoint: String,
98 #[serde(default)]
99 storage_class: String,
100}
101
102impl Bucket {
103 pub fn new(
104 name: String,
105 creation_date: String,
106 location: String,
107 extranet_endpoint: String,
108 intranet_endpoint: String,
109 storage_class: String,
110 ) -> Self {
111 Bucket {
112 name,
113 creation_date,
114 location,
115 extranet_endpoint,
116 intranet_endpoint,
117 storage_class,
118 }
119 }
120
121 pub fn name(&self) -> &str {
122 &self.name
123 }
124
125 pub fn creation_date(&self) -> &str {
126 &self.creation_date
127 }
128
129 pub fn location(&self) -> &str {
130 &self.location
131 }
132
133 pub fn extranet_endpoint(&self) -> &str {
134 &self.extranet_endpoint
135 }
136
137 pub fn intranet_endpoint(&self) -> &str {
138 &self.intranet_endpoint
139 }
140
141 pub fn storage_class(&self) -> &str {
142 &self.storage_class
143 }
144}
145
146pub trait ServiceAPI {
147 fn list_bucket<S, R>(&self, resources: R) -> Result<ListBuckets, Error>
148 where
149 S: AsRef<str>,
150 R: Into<Option<HashMap<S, Option<S>>>>;
151}
152
153impl<'a> ServiceAPI for OSS<'a> {
154 fn list_bucket<S, R>(&self, resources: R) -> Result<ListBuckets, Error>
155 where
156 S: AsRef<str>,
157 R: Into<Option<HashMap<S, Option<S>>>>,
158 {
159 let resources_str = if let Some(r) = resources.into() {
160 self.get_resources_str(&r)
161 } else {
162 String::new()
163 };
164 let host = self.endpoint();
165 let date = self.date();
166
167 let mut headers = HeaderMap::new();
168 headers.insert(DATE, date.parse()?);
169 let authorization = self.oss_sign(
170 "GET",
171 self.key_id(),
172 self.key_secret(),
173 "",
174 "",
175 &resources_str,
176 &headers,
177 );
178 headers.insert("Authorization", authorization.parse()?);
179
180 let resp = reqwest::blocking::Client::new()
181 .get(host)
182 .headers(headers)
183 .send()?;
184
185 let body = resp.text()?;
186 let list_buckets = quick_xml::de::from_str::<ListBuckets>(&body)?;
187
188 Ok(list_buckets)
189 }
190}