rusty_oss/actions/
get_object.rs

1use std::time::Duration;
2
3use time::OffsetDateTime;
4use url::Url;
5
6use super::OSSAction;
7use crate::actions::Method;
8use crate::signing::sign;
9use crate::{Bucket, Credentials, Map};
10
11/// Retrieve an object from OSS, using a `GET` request.
12///
13/// Find out more about `GetObject` from the [OSS API Reference][api]
14///
15/// [api]: https://help.aliyun.com/zh/oss/developer-reference/getobject
16#[derive(Debug, Clone)]
17pub struct GetObject<'a> {
18    bucket: &'a Bucket,
19    credentials: Option<&'a Credentials>,
20    object: &'a str,
21
22    query: Map<'a>,
23    headers: Map<'a>,
24}
25
26impl<'a> GetObject<'a> {
27    #[inline]
28    pub fn new(bucket: &'a Bucket, credentials: Option<&'a Credentials>, object: &'a str) -> Self {
29        Self {
30            bucket,
31            credentials,
32            object,
33
34            query: Map::new(),
35            headers: Map::new(),
36        }
37    }
38}
39
40impl<'a> OSSAction<'a> for GetObject<'a> {
41    const METHOD: Method = Method::Get;
42
43    fn query_mut(&mut self) -> &mut Map<'a> {
44        &mut self.query
45    }
46
47    fn headers_mut(&mut self) -> &mut Map<'a> {
48        &mut self.headers
49    }
50
51    fn sign_with_time(&self, expires_in: Duration, time: &OffsetDateTime) -> Url {
52        let url = self.bucket.object_url(self.object).unwrap();
53
54        match self.credentials {
55            Some(credentials) => sign(
56                time,
57                Method::Get,
58                url,
59                credentials.key(),
60                credentials.secret(),
61                credentials.token(),
62                self.bucket.region(),
63                expires_in.as_secs(),
64                self.query.iter(),
65                self.headers.iter(),
66            ),
67            None => crate::signing::util::add_query_params(url, self.query.iter()),
68        }
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use time::OffsetDateTime;
75
76    use pretty_assertions::assert_eq;
77
78    use super::*;
79    use crate::{Bucket, Credentials, UrlStyle};
80
81    #[test]
82    fn oss_example() {
83        // Fri, 24 May 2013 00:00:00 GMT
84        let date = OffsetDateTime::from_unix_timestamp(1369353600).unwrap();
85        let expires_in = Duration::from_secs(86400);
86
87        let endpoint = "https://oss-cn-hangzhou.aliyuncs.com".parse().unwrap();
88        let bucket = Bucket::new(
89            endpoint,
90            UrlStyle::VirtualHost,
91            "examplebucket",
92            "cn-hangzhou",
93        )
94        .unwrap();
95        let credentials = Credentials::new(
96            "access_key_id",
97            "access_key_secret",
98        );
99
100        let action = GetObject::new(&bucket, Some(&credentials), "test.html");
101
102        let url = action.sign_with_time(expires_in, &date);
103        let expected = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/test.html?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=87a3e44b13e6fd201d84127b43e3360bc60c062aabd77b9f3dc893a383b1f02b";
104
105        assert_eq!(expected, url.as_str());
106    }
107
108    #[test]
109    fn oss_example_custom_query() {
110        // Fri, 24 May 2013 00:00:00 GMT
111        let date = OffsetDateTime::from_unix_timestamp(1369353600).unwrap();
112        let expires_in = Duration::from_secs(86400);
113
114        let endpoint = "https://oss-cn-hangzhou.aliyuncs.com".parse().unwrap();
115        let bucket = Bucket::new(
116            endpoint,
117            UrlStyle::VirtualHost,
118            "examplebucket",
119            "cn-hangzhou",
120        )
121        .unwrap();
122        let credentials = Credentials::new(
123            "access_key_id",
124            "access_key_secret",
125        );
126
127        let mut action = GetObject::new(&bucket, Some(&credentials), "test.txt");
128        action
129            .query_mut()
130            .insert("response-content-type", "text/plain");
131
132        let url = action.sign_with_time(expires_in, &date);
133        let expected = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/test.txt?response-content-type=text%2Fplain&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=4f195f7e78bcb373104fe630567003f3b73b42e6b12a96b5d18b64755cacaf87";
134
135        assert_eq!(expected, url.as_str());
136    }
137
138    #[test]
139    fn anonymous_custom_query() {
140        let expires_in = Duration::from_secs(86400);
141
142        let endpoint = "https://oss-cn-hangzhou.aliyuncs.com".parse().unwrap();
143        let bucket = Bucket::new(
144            endpoint,
145            UrlStyle::VirtualHost,
146            "examplebucket",
147            "cn-hangzhou",
148        )
149        .unwrap();
150
151        let mut action = GetObject::new(&bucket, None, "test.txt");
152        action
153            .query_mut()
154            .insert("response-content-type", "text/plain");
155
156        let url = action.sign(expires_in);
157        let expected =
158            "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/test.txt?response-content-type=text%2Fplain";
159
160        assert_eq!(expected, url.as_str());
161    }
162}