rust_qcos/
client.rs

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