wae_storage/providers/
oss.rs1use crate::{StorageConfig, StorageProvider, StorageResult};
4
5use base64::{Engine as _, engine::general_purpose::STANDARD};
6use chrono::Utc;
7use hmac::{Hmac, Mac};
8use sha1::Sha1;
9use url::Url;
10use wae_types::WaeError;
11
12pub struct OssProvider;
16
17impl StorageProvider for OssProvider {
18 fn sign_url(&self, path: &str, config: &StorageConfig) -> StorageResult<Url> {
19 if path.is_empty() {
20 return Err(WaeError::invalid_params("path", "Empty path"));
21 }
22
23 if path.starts_with("http://") || path.starts_with("https://") {
24 return Url::parse(path).map_err(|e| WaeError::invalid_params("path", e.to_string()));
25 }
26
27 let clean_path = path.trim_start_matches('/');
28 let expires = Utc::now().timestamp() + 3600;
29
30 let host_str =
31 config.cdn_url.clone().unwrap_or_else(|| format!("https://{}.{}.aliyuncs.com", config.bucket, config.region));
32
33 let host_url =
34 if host_str.starts_with("http") { Url::parse(&host_str) } else { Url::parse(&format!("https://{}", host_str)) }
35 .map_err(|e| WaeError::invalid_params("host", e.to_string()))?;
36
37 let mut url = host_url.join(clean_path).map_err(|e| WaeError::invalid_params("path", e.to_string()))?;
38
39 let string_to_sign = format!("GET\n\n\n{}\n/{}/{}", expires, config.bucket, clean_path);
40
41 let mut mac =
42 Hmac::<Sha1>::new_from_slice(config.secret_key.as_bytes()).map_err(|e| WaeError::internal(e.to_string()))?;
43 mac.update(string_to_sign.as_bytes());
44 let signature = STANDARD.encode(mac.finalize().into_bytes());
45
46 url.query_pairs_mut()
47 .append_pair("OSSAccessKeyId", &config.secret_id)
48 .append_pair("Expires", &expires.to_string())
49 .append_pair("Signature", &signature);
50
51 Ok(url)
52 }
53
54 fn get_presigned_put_url(&self, key: &str, config: &StorageConfig) -> StorageResult<Url> {
55 let clean_key = key.trim_start_matches('/');
56 let expires = Utc::now().timestamp() + 900;
57
58 let host_str =
59 config.endpoint.clone().unwrap_or_else(|| format!("https://{}.{}.aliyuncs.com", config.bucket, config.region));
60
61 let host_url =
62 if host_str.starts_with("http") { Url::parse(&host_str) } else { Url::parse(&format!("https://{}", host_str)) }
63 .map_err(|e| WaeError::invalid_params("host", e.to_string()))?;
64
65 let mut url = host_url.join(clean_key).map_err(|e| WaeError::invalid_params("key", e.to_string()))?;
66
67 let string_to_sign = format!("PUT\n\n\n{}\n/{}/{}", expires, config.bucket, clean_key);
68
69 let mut mac =
70 Hmac::<Sha1>::new_from_slice(config.secret_key.as_bytes()).map_err(|e| WaeError::internal(e.to_string()))?;
71 mac.update(string_to_sign.as_bytes());
72 let signature = STANDARD.encode(mac.finalize().into_bytes());
73
74 url.query_pairs_mut()
75 .append_pair("OSSAccessKeyId", &config.secret_id)
76 .append_pair("Expires", &expires.to_string())
77 .append_pair("Signature", &signature);
78
79 Ok(url)
80 }
81}