huaweicloud_sdk_rust_obs/
config.rs

1use lazy_static::lazy_static;
2use std::{collections::HashMap, time::Duration};
3
4lazy_static! {
5    static ref SUB_RESOURCES: Vec<&'static str> = vec![
6        "CDNNotifyConfiguration",
7        "acl",
8        "append",
9        "attname",
10        "backtosource",
11        "cors",
12        "customdomain",
13        "delete",
14        "deletebucket",
15        "directcoldaccess",
16        "encryption",
17        "inventory",
18        "length",
19        "lifecycle",
20        "location",
21        "logging",
22        "metadata",
23        "mirrorBackToSource",
24        "modify",
25        "name",
26        "notification",
27        "obscompresspolicy",
28        "orchestration",
29        "partNumber",
30        "policy",
31        "position",
32        "quota",
33        "rename",
34        "replication",
35        "response-cache-control",
36        "response-content-disposition",
37        "response-content-encoding",
38        "response-content-language",
39        "response-content-type",
40        "response-expires",
41        "restore",
42        "storageClass",
43        "storagePolicy",
44        "storageinfo",
45        "tagging",
46        "torrent",
47        "truncate",
48        "uploadId",
49        "uploads",
50        "versionId",
51        "versioning",
52        "versions",
53        "website",
54        "x-image-process",
55        "x-image-save-bucket",
56        "x-image-save-object",
57        "x-obs-security-token",
58        "object-lock",
59        "retention"
60    ];
61}
62
63#[derive(Debug, Clone)]
64pub enum SignatureType {
65    V2,
66    V4,
67    OBS,
68}
69
70#[derive(Debug, Default, Clone)]
71pub struct SecurityHolder {
72    ak: String,
73    sk: String,
74    security_token: String,
75}
76impl SecurityHolder {
77    pub fn new(ak: String, sk: String, security_token: String) -> Self {
78        Self {
79            ak,
80            sk,
81            security_token,
82        }
83    }
84
85    pub fn ak(&self) -> &str {
86        self.ak.as_ref()
87    }
88
89    pub fn sk(&self) -> &str {
90        self.sk.as_ref()
91    }
92
93    pub fn security_token(&self) -> &str {
94        self.security_token.as_ref()
95    }
96}
97
98#[derive(Debug, Clone)]
99pub struct Config {
100    pub(crate) security_providers: Vec<SecurityHolder>,
101    pub(crate) endpoint: String,
102    pub(crate) is_secure: bool,
103    pub(crate) region: String,
104    pub(crate) timeout: Duration,
105    pub(crate) signature_type: SignatureType,
106}
107
108pub type CanonicalizedResource = String;
109pub type RequestUri = String;
110
111impl Config {
112    pub fn security_providers(&self) -> &[SecurityHolder] {
113        self.security_providers.as_ref()
114    }
115
116    pub fn format_urls(
117        &self,
118        bucket_name: &str,
119        object_key: &str,
120        params: Option<HashMap<String, String>>,
121    ) -> (RequestUri, CanonicalizedResource) {
122        let mut canonicalized_resource: CanonicalizedResource = String::from("/");
123        let mut uri: RequestUri = String::new();
124        if !bucket_name.is_empty() {
125            canonicalized_resource.push_str(bucket_name);
126            canonicalized_resource.push('/');
127            match self.signature_type {
128                SignatureType::V2 | SignatureType::OBS => {
129                    if !object_key.is_empty() {
130                        canonicalized_resource.push_str(object_key);
131                        uri.push_str(object_key);
132                    }
133                    if let Some(params) = params {
134                        canonicalized_resource.push('?');
135                        let mut uri_params = vec![];
136                        for (k, v) in &params {
137                            if v.is_empty() {
138                                uri_params.push(k.to_string());
139                            }else {
140                                uri_params.push(format!("{}={}", k, v));
141                            }
142                            if SUB_RESOURCES.contains(&k.as_str()) {
143                                if !canonicalized_resource.ends_with('?') {
144                                    canonicalized_resource.push('&');
145                                }
146                                canonicalized_resource.push_str(k);
147                                if !v.is_empty() {
148                                    canonicalized_resource.push('=');
149                                    canonicalized_resource.push_str(v);
150                                }
151                                
152                            }
153                        }
154                        if !uri_params.is_empty() {
155                            uri.push('?');
156                            uri.push_str(uri_params.join("&").as_str());
157                        }
158                    }
159                }
160                SignatureType::V4 => canonicalized_resource.push('/'),
161            }
162        }
163        (uri, canonicalized_resource.trim_end_matches('?').into())
164    }
165
166    /// 暂时不支持自定义域名
167    pub fn canonicalized_url(&self, bucket_name: &str, uri: &str) -> String {
168        if bucket_name.is_empty() {
169            String::from("/")
170        } else {
171            match self.signature_type {
172                SignatureType::V2 | SignatureType::OBS => {
173                    if uri.is_empty() {
174                        format!("/{}/", bucket_name)
175                    } else {
176                        format!("/{}/{}", bucket_name, uri)
177                    }
178                }
179                SignatureType::V4 => String::from("/"),
180            }
181        }
182    }
183
184    pub(crate) fn set_security_providers(&mut self, security_providers: Vec<SecurityHolder>) {
185        self.security_providers = security_providers;
186    }
187
188    pub(crate) fn set_endpoint(&mut self, endpoint: String) {
189        self.endpoint = endpoint;
190    }
191
192    pub(crate) fn set_is_secure(&mut self, is_secure: bool) {
193        self.is_secure = is_secure;
194    }
195
196    pub(crate) fn set_region(&mut self, region: String) {
197        self.region = region;
198    }
199
200    pub(crate) fn set_timeout(&mut self, timeout: Duration) {
201        self.timeout = timeout;
202    }
203
204    pub(crate) fn set_signature_type(&mut self, signature_type: SignatureType) {
205        self.signature_type = signature_type;
206    }
207
208    pub(crate) fn timeout(&self) -> Duration {
209        self.timeout
210    }
211
212    pub fn endpoint(&self) -> &str {
213        self.endpoint.as_ref()
214    }
215}