huaweicloud_sdk_rust_obs/
bucket.rs

1use std::collections::HashMap;
2
3use crate::{
4    client::Client,
5    error::{status_to_response, ObsError},
6    model::bucket::{
7        copy_object::CopyObjectResult, create_bucket::CreateBucketRequest,
8        list_bucket::ListAllMyBucketsResult, list_object::ListBucketResult,
9        location::Location,
10    },
11    object::ObjectTrait,
12};
13use reqwest::Method;
14
15#[async_trait::async_trait]
16pub trait BucketTrait {
17    /// 获取桶列表
18    /// # Example
19    ///
20    /// ```
21    /// let obs = client::Client::builder()
22    ///  .endpoint("https://obs.ap-southeast-1.myhuaweicloud.com")
23    ///  .security_provider(&ak, &sk)
24    ///  .build()?;
25    /// let _res = obs.list_buckets().await?;
26    /// ```
27    async fn list_buckets(&self) -> Result<ListAllMyBucketsResult, ObsError>;
28    /// 创建桶
29    ///
30    /// - name: 桶名
31    /// - location: 桶地区
32    ///
33    /// # Example
34    ///
35    /// Basic usage:
36    ///
37    /// ```
38    /// let obs = client::Client::builder()
39    ///  .endpoint("https://obs.ap-southeast-1.myhuaweicloud.com")
40    ///  .security_provider(&ak, &sk)
41    ///  .build()?;
42    /// let _res = obs.create_bucket("bucket", "cn-north-4").await?;
43    /// ```
44    async fn create_bucket<S1, S2>(&self, name: S1, location: Option<S2>) -> Result<(), ObsError>
45    where
46        S1: AsRef<str> + Send,
47        S2: AsRef<str> + Send;
48
49    /// 列举桶内对象
50    ///
51    /// - `name`: 桶名
52    /// - `prefix`: 列举以指定的字符串prefix开头的对象。
53    /// - `marker`: 列举桶内对象列表时,指定一个标识符,从该标识符以后按字典顺序返回对象列表。该字段仅用于非多版本列举。
54    /// - `max-keys`: 指定返回的最大对象数,返回的对象列表将是按照字典顺序的最多前max-keys个对象,范围是[1,1000],超出范围时,按照默认的1000进行处理。
55    ///
56    /// # Examples
57    ///
58    /// Basic usage:
59    ///
60    /// ```
61    /// let obs = client::Client::builder()
62    ///  .endpoint("https://obs.ap-southeast-1.myhuaweicloud.com")
63    ///  .security_provider(&ak, &sk)
64    ///  .build()?;
65    /// let _res = obs.list_objects('bucket', None, None, None).await?;
66    /// ```
67    async fn list_objects<S1>(
68        &self,
69        name: S1,
70        prefix: Option<&str>,
71        marker: Option<&str>,
72        max_keys: Option<usize>,
73    ) -> Result<ListBucketResult, ObsError>
74    where
75        S1: AsRef<str> + Send;
76
77    /// 获取桶区域位置
78    async fn bucket_location<S1>(&self, name: S1) -> Result<Location, ObsError>
79    where
80        S1: AsRef<str> + Send;
81}
82
83pub struct Bucket<'a> {
84    name: &'a str,
85    client: &'a Client,
86}
87
88impl<'a> Bucket<'a> {
89    pub fn new(name: &'a str, client: &'a Client) -> Self {
90        Self { name, client }
91    }
92
93    pub async fn put_object<S>(&self, key: S, object: &[u8]) -> Result<(), ObsError>
94    where
95        S: AsRef<str> + Send,
96    {
97        self.client
98            .put_object(self.name, key.as_ref(), object)
99            .await
100    }
101
102    pub async fn copy_object<S1, S2>(&self, src: S1, dest: S2) -> Result<CopyObjectResult, ObsError>
103    where
104        S1: AsRef<str> + Send,
105        S2: AsRef<str> + Send,
106    {
107        self.client.copy_object(self.name, src, dest).await
108    }
109
110    pub async fn list_objects(
111        &self,
112        prefix: Option<&str>,
113        marker: Option<&str>,
114        max_keys: Option<usize>,
115    ) -> Result<ListBucketResult, ObsError> {
116        self.client
117            .list_objects(self.name, prefix, marker, max_keys)
118            .await
119    }
120
121    pub async fn location(&self) -> Result<Location, ObsError> {
122        self.client.bucket_location(self.name).await
123    }
124}
125
126#[async_trait::async_trait]
127impl BucketTrait for Client {
128    async fn list_buckets(&self) -> Result<ListAllMyBucketsResult, ObsError> {
129        let resp = self
130            .do_action_without_bucket_name(Method::GET, "", None, None, None::<String>)
131            .await?;
132        let status = resp.status();
133        let text = resp.text().await?;
134        status_to_response::<ListAllMyBucketsResult>(status, text)
135    }
136
137    async fn create_bucket<S1, S2>(&self, name: S1, location: Option<S2>) -> Result<(), ObsError>
138    where
139        S1: AsRef<str> + Send,
140        S2: AsRef<str> + Send,
141    {
142        let body = if let Some(loc) = location {
143            let xml = CreateBucketRequest::new(loc.as_ref());
144            serde_xml_rs::to_string(&xml)?
145        } else {
146            String::new()
147        };
148
149        let _res = self
150            .do_action(Method::PUT, name, "", None, None, Some(body))
151            .await?;
152
153        Ok(())
154    }
155
156    async fn list_objects<S1>(
157        &self,
158        name: S1,
159        prefix: Option<&str>,
160        marker: Option<&str>,
161        max_keys: Option<usize>,
162    ) -> Result<ListBucketResult, ObsError>
163    where
164        S1: AsRef<str> + Send,
165    {
166        let mut params = HashMap::new();
167        params.insert("delimiter".into(), "/".to_string());
168
169        if let Some(m) = marker {
170            params.insert("marker".into(), m.into());
171        }
172
173        if let Some(mk) = max_keys {
174            params.insert("max-keys".into(), mk.to_string());
175        }
176
177        if let Some(p) = prefix {
178            params.insert("prefix".into(), p.into());
179        }
180
181        let resp = self
182            .do_action(Method::GET, name, "", None, Some(params), None::<String>)
183            .await?;
184        let status = resp.status();
185        let text = resp.text().await?;
186        // println!("{}",&text);
187        status_to_response::<ListBucketResult>(status, text)
188    }
189
190    async fn bucket_location<S1>(&self, name: S1) -> Result<Location, ObsError>
191    where
192        S1: AsRef<str> + Send,
193    {
194        let mut params = HashMap::new();
195        params.insert("location".to_string(), "".to_string());
196
197        let resp = self
198            .do_action(
199                Method::GET,
200                name,
201                "",
202                None,
203                Some(params),
204                None::<String>,
205            )
206            .await?;
207        let status = resp.status();
208        let text = resp.text().await?;
209
210        status_to_response::<Location>(status, text)
211    }
212}