rusty_oss/actions/multipart_upload/
abort.rs

1use std::iter;
2use std::time::Duration;
3
4use time::OffsetDateTime;
5use url::Url;
6
7use crate::actions::Method;
8use crate::actions::OSSAction;
9use crate::signing::sign;
10use crate::sorting_iter::SortingIterator;
11use crate::{Bucket, Credentials, Map};
12
13/// Abort multipart upload.
14///
15/// This also cleans up any previously uploaded part.
16///
17/// Find out more about `AbortMultipartUpload` from the [OSS API Reference][api]
18///
19/// [api]: https://help.aliyun.com/zh/oss/developer-reference/abortmultipartupload
20#[derive(Debug, Clone)]
21pub struct AbortMultipartUpload<'a> {
22    bucket: &'a Bucket,
23    credentials: Option<&'a Credentials>,
24    object: &'a str,
25
26    upload_id: &'a str,
27
28    query: Map<'a>,
29    headers: Map<'a>,
30}
31
32impl<'a> AbortMultipartUpload<'a> {
33    #[inline]
34    pub fn new(
35        bucket: &'a Bucket,
36        credentials: Option<&'a Credentials>,
37        object: &'a str,
38        upload_id: &'a str,
39    ) -> Self {
40        Self {
41            bucket,
42            credentials,
43            object,
44
45            upload_id,
46
47            query: Map::new(),
48            headers: Map::new(),
49        }
50    }
51}
52
53impl<'a> OSSAction<'a> for AbortMultipartUpload<'a> {
54    const METHOD: Method = Method::Delete;
55
56    fn query_mut(&mut self) -> &mut Map<'a> {
57        &mut self.query
58    }
59
60    fn headers_mut(&mut self) -> &mut Map<'a> {
61        &mut self.headers
62    }
63
64    fn sign_with_time(&self, expires_in: Duration, time: &OffsetDateTime) -> Url {
65        let url = self.bucket.object_url(self.object).unwrap();
66        let query = iter::once(("uploadId", self.upload_id));
67
68        match self.credentials {
69            Some(credentials) => sign(
70                time,
71                Method::Delete,
72                url,
73                credentials.key(),
74                credentials.secret(),
75                credentials.token(),
76                self.bucket.region(),
77                expires_in.as_secs(),
78                SortingIterator::new(query, self.query.iter()),
79                self.headers.iter(),
80            ),
81            None => crate::signing::util::add_query_params(url, query),
82        }
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use time::OffsetDateTime;
89
90    use pretty_assertions::assert_eq;
91
92    use super::*;
93    use crate::{Bucket, Credentials, UrlStyle};
94
95    #[test]
96    fn oss_example() {
97        // Fri, 24 May 2013 00:00:00 GMT
98        let date = OffsetDateTime::from_unix_timestamp(1369353600).unwrap();
99        let expires_in = Duration::from_secs(86400);
100
101        let endpoint = "https://oss-cn-hangzhou.aliyuncs.com".parse().unwrap();
102        let bucket = Bucket::new(
103            endpoint,
104            UrlStyle::VirtualHost,
105            "examplebucket",
106            "cn-hangzhou",
107        )
108        .unwrap();
109        let credentials = Credentials::new(
110            "access_key_id",
111            "access_key_secret",
112        );
113
114        let action = AbortMultipartUpload::new(&bucket, Some(&credentials), "test.txt", "abcd");
115
116        let url = action.sign_with_time(expires_in, &date);
117        let expected = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/test.txt?uploadId=abcd&x-oss-additional-headers=host&x-oss-credential=access_key_id%2F20130524%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-date=20130524T000000Z&x-oss-expires=86400&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-signature=97ac3a468ac3694e201bdae370130f525883290b05495cdefb08cb286af12132";
118
119        assert_eq!(expected, url.as_str());
120    }
121
122    #[test]
123    fn anonymous_custom_query() {
124        let expires_in = Duration::from_secs(86400);
125
126        let endpoint = "https://oss-cn-hangzhou.aliyuncs.com".parse().unwrap();
127        let bucket = Bucket::new(
128            endpoint,
129            UrlStyle::VirtualHost,
130            "examplebucket",
131            "cn-hangzhou",
132        )
133        .unwrap();
134
135        let action = AbortMultipartUpload::new(&bucket, None, "test.txt", "abcd");
136        let url = action.sign(expires_in);
137        let expected = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/test.txt?uploadId=abcd";
138
139        assert_eq!(expected, url.as_str());
140    }
141}