Skip to main content

ali_oss_rs/
symlink.rs

1//! Object symlink module
2
3use async_trait::async_trait;
4
5use crate::symlink_common::{build_get_symlink_request, build_put_symlink_request, GetSymlinkOptions, PutSymlinkOptions, PutSymlinkResult};
6use crate::{Client, Result};
7
8#[async_trait]
9pub trait ObjectSymlinkOperations {
10    /// Put a symlink object.
11    ///
12    /// `target_object_key` should be a full and valid object key.
13    ///
14    /// Official document: <https://help.aliyun.com/zh/oss/developer-reference/putsymlink>
15    async fn put_symlink<S1, S2, S3>(
16        &self,
17        bucket_name: S1,
18        symlink_object_key: S2,
19        target_object_key: S3,
20        options: Option<PutSymlinkOptions>,
21    ) -> Result<PutSymlinkResult>
22    where
23        S1: AsRef<str> + Send,
24        S2: AsRef<str> + Send,
25        S3: AsRef<str> + Send;
26
27    /// Get a symlink object. The returned string is the target object key
28    ///
29    /// Official document: <https://help.aliyun.com/zh/oss/developer-reference/getsymlink>
30    async fn get_symlink<S1, S2>(&self, bucket_name: S1, symlink_object_key: S2, options: Option<GetSymlinkOptions>) -> Result<String>
31    where
32        S1: AsRef<str> + Send,
33        S2: AsRef<str> + Send;
34}
35
36#[async_trait]
37impl ObjectSymlinkOperations for Client {
38    /// Put a symlink object.
39    ///
40    /// `target_object_key` should be a full and valid object key.
41    ///
42    /// Official document: <https://help.aliyun.com/zh/oss/developer-reference/putsymlink>
43    async fn put_symlink<S1, S2, S3>(
44        &self,
45        bucket_name: S1,
46        symlink_object_key: S2,
47        target_object_key: S3,
48        options: Option<PutSymlinkOptions>,
49    ) -> Result<PutSymlinkResult>
50    where
51        S1: AsRef<str> + Send,
52        S2: AsRef<str> + Send,
53        S3: AsRef<str> + Send,
54    {
55        let request = build_put_symlink_request(bucket_name.as_ref(), symlink_object_key.as_ref(), target_object_key.as_ref(), &options)?;
56        let (headers, _) = self.do_request::<()>(request).await?;
57        Ok(headers.into())
58    }
59
60    /// Get a symlink object. The returned string is the target object key
61    ///
62    /// Official document: <https://help.aliyun.com/zh/oss/developer-reference/getsymlink>
63    async fn get_symlink<S1, S2>(&self, bucket_name: S1, symlink_object_key: S2, options: Option<GetSymlinkOptions>) -> Result<String>
64    where
65        S1: AsRef<str> + Send,
66        S2: AsRef<str> + Send,
67    {
68        let request = build_get_symlink_request(bucket_name.as_ref(), symlink_object_key.as_ref(), &options)?;
69        let (headers, _) = self.do_request::<()>(request).await?;
70        let object_key = headers.get("x-oss-symlink-target").unwrap_or(&String::new()).to_string();
71
72        Ok(urlencoding::decode(&object_key)?.to_string())
73    }
74}
75
76#[cfg(test)]
77mod test_symlink_async {
78    use std::sync::Once;
79
80    use uuid::Uuid;
81
82    use crate::{
83        object::ObjectOperations,
84        object_common::{PutObjectApiResponse, PutObjectResult},
85        symlink::ObjectSymlinkOperations,
86        symlink_common::PutSymlinkOptionsBuilder,
87        Client,
88    };
89
90    static INIT: Once = Once::new();
91
92    fn setup() {
93        INIT.call_once(|| {
94            simple_logger::init_with_level(log::Level::Debug).unwrap();
95            dotenvy::dotenv().unwrap();
96        });
97    }
98
99    #[tokio::test]
100    async fn test_symlink_async() {
101        log::debug!("test symlink");
102        setup();
103
104        let client = Client::from_env();
105        let bucket_name = "yuanyq-2";
106        let object_key = format!("versioning-test/{}.webp", Uuid::new_v4());
107        let file_path = "/home/yuanyq/Pictures/test-7.webp";
108
109        let link_name = format!("versioning-test/{}-link.webp", Uuid::new_v4());
110
111        let response = client.put_object_from_file(bucket_name, &object_key, file_path, None).await;
112        assert!(response.is_ok());
113
114        let ret = response.unwrap();
115        let version_id = if let PutObjectResult::ApiResponse(PutObjectApiResponse {
116            request_id: _,
117            etag: _,
118            content_md5: _,
119            hash_crc64ecma: _,
120            version_id,
121        }) = ret
122        {
123            assert!(version_id.is_some());
124            version_id.clone().unwrap()
125        } else {
126            panic!("Unexpected response type");
127        };
128
129        log::debug!("version id: {}", version_id);
130
131        let options = PutSymlinkOptionsBuilder::new().metadata("x-oss-meta-a", "meta value b").build();
132
133        let response = client.put_symlink(bucket_name, &link_name, &object_key, Some(options)).await;
134        assert!(response.is_ok());
135
136        let ret = response.unwrap();
137        assert!(ret.version_id.is_some());
138
139        let response = client.get_symlink(bucket_name, &link_name, None).await;
140        assert!(response.is_ok());
141        let ret = response.unwrap();
142        assert_eq!(ret, object_key);
143
144        let response = client.delete_object(bucket_name, &link_name, None).await;
145        assert!(response.is_ok());
146
147        let response = client.delete_object(bucket_name, &object_key, None).await;
148        assert!(response.is_ok());
149    }
150}