1use super::model::error::Error as ErrorResponse;
5use crate::{
6 errors::status_to_response,
7 model::{ object::ListBucketResult, Empty },
8 oss::{ ObjectMeta, RequestType },
9 prelude::OSS,
10};
11use std::collections::HashMap;
12
13use super::errors::OSSError;
14
15use async_trait::async_trait;
16use bytes::Bytes;
17use reqwest::StatusCode;
18
19#[async_trait]
20pub trait ObjectAPI {
21 async fn list_object<S, H, R>(
22 &self,
23 headers: H,
24 resources: R
25 )
26 -> Result<ListBucketResult, OSSError>
27 where
28 S: AsRef<str>,
29 H: Into<Option<HashMap<S, S>>> + Send,
30 R: Into<Option<HashMap<S, Option<S>>>> + Send;
31
32 async fn list_object_v2<S>(
33 &self,
34 prefix: Option<S>,
35 delimiter: Option<S>
36 ) -> Result<ListBucketResult, OSSError>
37 where S: AsRef<str> + Send;
38
39 async fn get_object<S1, S2, H, R>(
40 &self,
41 object_name: S1,
42 headers: H,
43 resources: R
44 )
45 -> Result<Bytes, OSSError>
46 where
47 S1: AsRef<str> + Send,
48 S2: AsRef<str> + Send,
49 H: Into<Option<HashMap<S2, S2>>> + Send,
50 R: Into<Option<HashMap<S2, Option<S2>>>> + Send;
51
52 async fn put_object<S1, S2, H, R>(
53 &self,
54 buf: &[u8],
55 object_name: S1,
56 headers: H,
57 resources: R
58 )
59 -> Result<(), OSSError>
60 where
61 S1: AsRef<str> + Send,
62 S2: AsRef<str> + Send,
63 H: Into<Option<HashMap<S2, S2>>> + Send,
64 R: Into<Option<HashMap<S2, Option<S2>>>> + Send;
65
66 async fn append_object<S1, S2, H, R>(
67 &self,
68 buf: &[u8],
69 object_name: S1,
70 headers: H,
71 resources: R
72 )
73 -> Result<Option<u64>, OSSError>
74 where
75 S1: AsRef<str> + Send,
76 S2: AsRef<str> + Send,
77 H: Into<Option<HashMap<S2, S2>>> + Send,
78 R: Into<Option<HashMap<S2, Option<S2>>>> + Send;
79
80 async fn copy_object_from_object<S1, S2, S3, H, R>(
81 &self,
82 src: S1,
83 dest: S2,
84 headers: H,
85 resources: R
86 )
87 -> Result<(), OSSError>
88 where
89 S1: AsRef<str> + Send,
90 S2: AsRef<str> + Send,
91 S3: AsRef<str> + Send,
92 H: Into<Option<HashMap<S3, S3>>> + Send,
93 R: Into<Option<HashMap<S3, Option<S3>>>> + Send;
94
95 async fn delete_object<S>(&self, object_name: S) -> Result<(), OSSError>
96 where S: AsRef<str> + Send;
97
98 async fn head_object<S>(&self, object_name: S) -> Result<ObjectMeta, OSSError>
99 where S: AsRef<str> + Send;
100}
101
102#[async_trait]
103impl<'a> ObjectAPI for OSS<'a> {
104 async fn list_object<S, H, R>(
105 &self,
106 headers: H,
107 resources: R
108 )
109 -> Result<ListBucketResult, OSSError>
110 where
111 S: AsRef<str>,
112 H: Into<Option<HashMap<S, S>>> + Send,
113 R: Into<Option<HashMap<S, Option<S>>>> + Send
114 {
115 let (host, headers) = self.build_request(
116 RequestType::Get,
117 String::new(),
118 headers,
119 resources
120 )?;
121
122 let resp = self.http_client.get(host).headers(headers).send().await?;
123
124 let status = resp.status();
125 let text = resp.text().await?;
126 status_to_response(status, text)
127 }
128
129 async fn list_object_v2<S>(
130 &self,
131 prefix: Option<S>,
132 delimiter: Option<S>
133 ) -> Result<ListBucketResult, OSSError>
134 where S: AsRef<str> + Send
135 {
136 let mut resources = HashMap::new();
137 resources.insert("list-type".to_string(), Some("2".to_string()));
138 resources.insert(
139 "delimiter".to_string(),
140 delimiter.map(|s| s.as_ref().to_string())
141 );
142 resources.insert(
143 "prefix".to_string(),
144 prefix.map(|s| s.as_ref().to_string())
145 );
146 resources.insert("max-keys".to_string(), Some("1000".to_string()));
147 let headers = HashMap::new();
148 let (host, headers) = self.build_request(
149 RequestType::Get,
150 String::new(),
151 Some(headers),
152 resources
153 )?;
154
155 let resp = self.http_client.get(host).headers(headers).send().await?;
156
157 let status = resp.status();
158 let text = resp.text().await?;
159 status_to_response(status, text)
160 }
161
162 async fn get_object<S1, S2, H, R>(
163 &self,
164 object_name: S1,
165 headers: H,
166 resources: R
167 )
168 -> Result<Bytes, OSSError>
169 where
170 S1: AsRef<str> + Send,
171 S2: AsRef<str> + Send,
172 H: Into<Option<HashMap<S2, S2>>> + Send,
173 R: Into<Option<HashMap<S2, Option<S2>>>> + Send
174 {
175 let (host, headers) = self.build_request(
176 RequestType::Get,
177 object_name,
178 headers,
179 resources
180 )?;
181
182 let resp = self.http_client.get(&host).headers(headers).send().await?;
183
184 let status = resp.status();
185
186 if status.is_success() {
187 Ok(resp.bytes().await?)
188 } else {
189 Err(OSSError::Object {
190 status_code: status,
191 message: "get object fail".into(),
192 })
193 }
194 }
195
196 async fn append_object<S1, S2, H, R>(
197 &self,
198 buf: &[u8],
199 object_name: S1,
200 headers: H,
201 resources: R
202 )
203 -> Result<Option<u64>, OSSError>
204 where
205 S1: AsRef<str> + Send,
206 S2: AsRef<str> + Send,
207 H: Into<Option<HashMap<S2, S2>>> + Send,
208 R: Into<Option<HashMap<S2, Option<S2>>>> + Send
209 {
210 let (host, headers) = self.build_request(
215 RequestType::Post,
216 object_name,
217 headers,
218 resources
219 )?;
220 let resp = self.http_client.post(&host).headers(headers).body(buf.to_owned()).send().await?;
221 let status = resp.status();
222
223 let resp_headers = resp.headers();
224 match status {
225 | StatusCode::OK
226 | StatusCode::NO_CONTENT
227 | StatusCode::CREATED
228 | StatusCode::ACCEPTED => {
229 let next_position = if
230 let Some(next) = resp_headers.get("x-oss-next-append-position")
231 {
232 let next = String::from_utf8_lossy(next.as_bytes()).to_string();
233 match next.parse::<u64>() {
234 Ok(u) => Some(u),
235 Err(_) => None,
236 }
237 } else {
238 None
239 };
240 Ok(next_position)
241 }
242 StatusCode::BAD_REQUEST | StatusCode::FORBIDDEN | StatusCode::CONFLICT => {
243 let text = resp.text().await?;
244 let er: ErrorResponse = serde_xml_rs::from_str(&text)?;
246 Err(OSSError::Object {
247 status_code: status,
248 message: er.message,
249 })
250 }
251 _ => Err(OSSError::Unknown),
252 }
253 }
254
255 async fn put_object<S1, S2, H, R>(
256 &self,
257 buf: &[u8],
258 object_name: S1,
259 headers: H,
260 resources: R
261 )
262 -> Result<(), OSSError>
263 where
264 S1: AsRef<str> + Send,
265 S2: AsRef<str> + Send,
266 H: Into<Option<HashMap<S2, S2>>> + Send,
267 R: Into<Option<HashMap<S2, Option<S2>>>> + Send
268 {
269 let (host, headers) = self.build_request(
270 RequestType::Put,
271 object_name,
272 headers,
273 resources
274 )?;
275
276 let resp = self.http_client.put(&host).headers(headers).body(buf.to_owned()).send().await?;
277 let status = resp.status();
278 let text = resp.text().await?;
279
280 let _ = status_to_response::<Empty>(status, text)?;
281 Ok(())
282 }
283
284 async fn copy_object_from_object<S1, S2, S3, H, R>(
285 &self,
286 src: S1,
287 dest: S2,
288 headers: H,
289 resources: R
290 )
291 -> Result<(), OSSError>
292 where
293 S1: AsRef<str> + Send,
294 S2: AsRef<str> + Send,
295 S3: AsRef<str> + Send,
296 H: Into<Option<HashMap<S3, S3>>> + Send,
297 R: Into<Option<HashMap<S3, Option<S3>>>> + Send
298 {
299 let (host, mut headers) = self.build_request(RequestType::Put, dest, headers, resources)?;
300 headers.insert("x-oss-copy-source", src.as_ref().parse()?);
301
302 let resp = self.http_client.put(&host).headers(headers).send().await?;
303
304 let status = resp.status();
305 let text = resp.text().await?;
306 status_to_response::<Empty>(status, text)?;
307 Ok(())
308 }
309
310 async fn delete_object<S>(&self, object_name: S) -> Result<(), OSSError>
311 where S: AsRef<str> + Send
312 {
313 let headers = HashMap::<String, String>::new();
314 let (host, headers) = self.build_request(
315 RequestType::Delete,
316 object_name,
317 Some(headers),
318 None
319 )?;
320
321 let resp = self.http_client.delete(&host).headers(headers).send().await?;
322
323 let status = resp.status();
324 let text = resp.text().await?;
325
326 let _ = status_to_response::<Empty>(status, text)?;
327 Ok(())
328 }
329
330 async fn head_object<S>(&self, object_name: S) -> Result<ObjectMeta, OSSError>
331 where S: AsRef<str> + Send
332 {
333 let (host, headers) = self.build_request(
334 RequestType::Head,
335 object_name,
336 None::<HashMap<String, String>>,
337 None
338 )?;
339
340 let resp = self.http_client.head(&host).headers(headers).send().await?;
341 let status = resp.status();
342 if resp.status().is_success() {
343 Ok(ObjectMeta::from_header_map(resp.headers())?)
344 } else {
345 Err(OSSError::Object {
346 status_code: status,
347 message: "head object error".into(),
348 })
349 }
350 }
351}