tencent_qcloud_cos_rs/
client.rs

1//! 接口客户端,所有的操作都基于该对象
2use crate::acl::AclHeader;
3use crate::request::Response;
4use crate::signer::Signer;
5/// 接口请求Client
6/// # Examples
7/// ```
8/// use tencent_qcloud_cos_rs::client::Client;
9/// let client = Client::new("secrect_id", "secrect_key", None, "bucket", "region");
10/// assert_eq!(client.get_host(), "bucket.cos.region.myqcloud.com");
11///```
12use chrono::Utc;
13use std::collections::HashMap;
14
15pub struct Client {
16    secrect_id: String,
17    secrect_key: String,
18    security_token: Option<String>,
19    bucket: String,
20    region: String,
21}
22
23impl Client {
24    pub fn new(
25        secrect_id: impl Into<String>,
26        secrect_key: impl Into<String>,
27        security_token: Option<String>,
28        bucket: impl Into<String>,
29        region: impl Into<String>,
30    ) -> Self {
31        Self {
32            secrect_id: secrect_id.into(),
33            secrect_key: secrect_key.into(),
34            security_token,
35            bucket: bucket.into(),
36            region: region.into(),
37        }
38    }
39
40    pub fn get_host(&self) -> String {
41        format!("{}.cos.{}.myqcloud.com", self.bucket, self.region)
42    }
43
44    pub fn get_secrect_key(&self) -> &str {
45        &self.secrect_key
46    }
47    pub fn get_secrect_id(&self) -> &str {
48        &self.secrect_id
49    }
50
51    // 生成通用的request headers, 包含`Host`及`Date`
52    pub fn gen_common_headers(&self) -> HashMap<String, String> {
53        let mut headers = HashMap::new();
54        headers.insert("Host".to_string(), self.get_host());
55        let now_str = Utc::now().format("%a, %d %b %Y %T GMT").to_string();
56        headers.insert("Date".to_string(), now_str);
57        headers
58    }
59
60    pub fn get_full_url_from_path(&self, path: &str) -> String {
61        format!("https://{}{}", self.get_host(), path)
62    }
63
64    pub fn get_path_from_object_key(&self, key: &str) -> String {
65        let mut url_path = key.to_string();
66        if !url_path.starts_with('/') {
67            url_path = format!("/{}", url_path);
68        }
69        url_path
70    }
71    // 生成查询bucket list的host
72    pub fn get_host_for_bucket_query(&self) -> String {
73        if self.region.is_empty() {
74            return "service.cos.myqcloud.com".to_string();
75        }
76        format!("cos.{}.myqcloud.com", self.region)
77    }
78
79    // 返回带有`Authorization` 的headers, 如果headers从参数传入, 除添加acl头部之外不会添加其他头
80    // 否则以`gen_common_headers` 返回作为初始值
81    pub fn get_headers_with_auth(
82        &self,
83        method: &str,
84        url_path: &str,
85        acl_header: Option<&AclHeader>,
86        origin_headers: Option<HashMap<String, String>>,
87        query: Option<&HashMap<String, String>>,
88    ) -> HashMap<String, String> {
89        let mut headers;
90        if let Some(origin_headers) = origin_headers {
91            headers = origin_headers;
92        } else {
93            headers = self.gen_common_headers();
94        }
95        if let Some(acl_header) = acl_header {
96            for (k, v) in acl_header.get_headers() {
97                headers.insert(k.to_string(), v.to_string());
98            }
99        }
100        let signature = Signer::new(method, url_path, Some(&headers), query).get_signature(
101            self.get_secrect_key(),
102            self.get_secrect_id(),
103            self.security_token.clone(),
104            7200,
105        );
106        headers.insert("Authorization".to_string(), signature);
107        headers
108    }
109
110    pub fn make_response(&self, resp: Result<Response, Response>) -> Response {
111        match resp {
112            Ok(e) => e,
113            Err(e) => e,
114        }
115    }
116
117    /// 获取预签名下载URL
118    /// 见[官网文档](https://cloud.tencent.com/document/product/436/35153)
119    pub fn get_presigned_download_url(&self, object_key: &str, expire: u32) -> String {
120        let url_path = self.get_path_from_object_key(object_key);
121        let full_url = self.get_full_url_from_path(url_path.as_str());
122        let mut headers = HashMap::new();
123        headers.insert("host".to_string(), self.get_host());
124        let signature = Signer::new("get", &url_path, Some(&headers), None).get_signature(
125            self.get_secrect_key(),
126            self.get_secrect_id(),
127            self.security_token.clone(),
128            expire,
129        );
130        format!("{url}?{signature}", url = full_url, signature = signature)
131    }
132}