rusty_oss/actions/multipart_upload/
abort.rs1use 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#[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 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}