alibaba_cloud_sdk_rust/services/dysmsapi/
client.rs

1#![allow(unused)]
2#![allow(non_upper_case_globals)]
3#![allow(non_snake_case)]
4#![allow(non_camel_case_types)]
5
6use crate::error::AliyunSDKError::AliyunSMSError;
7use crate::error::{AliyunResult, AliyunSDKError};
8use log::debug;
9use regex::Regex;
10use std::{
11    collections::HashMap,
12    env::consts::ARCH,
13    env::consts::OS,
14    hash::Hash,
15    io::{Error, ErrorKind},
16};
17
18use crate::sdk::client::Config;
19use crate::sdk::requests;
20use crate::sdk::responses;
21use crate::sdk::{
22    auth::credentials::AccessKeyCredential, requests::AcsRequest, responses::AcsResponse,
23};
24use crate::sdk::{auth::singers, endpoints};
25use crate::sdk::{
26    auth::singers::{Sign, Signer},
27    requests::BaseRequestExt,
28};
29use gostd::net::http;
30use gostd::strings;
31
32use super::endpoint;
33const Version: &str = "0.0.1";
34const EndpointType: &str = "central";
35
36pub type Client = crate::sdk::client::Client;
37impl Client {
38    pub fn NewClientWithAccessKey(
39        regionId: &str,
40        accessKeyId: &str,
41        accessKeySecret: &str,
42    ) -> AliyunResult<Client> {
43        let mut client = Client::default();
44        client.InitWithAccessKey(regionId, accessKeyId, accessKeySecret)?;
45        SetEndpointDataToClient(&mut client);
46        Ok(client)
47    }
48
49    pub fn InitWithAccessKey(
50        &mut self,
51        regionId: &str,
52        accessKeyId: &str,
53        accessKeySecret: &str,
54    ) -> AliyunResult<()> {
55        let config = self.InitClientConfig();
56        let credential = AccessKeyCredential {
57            AccessKeyId: accessKeyId.to_string(),
58            AccessKeySecret: accessKeySecret.to_string(),
59        };
60        self.InitWithOptions(regionId, &config, credential)?;
61        Ok(())
62    }
63
64    pub fn InitClientConfig(&mut self) -> Config {
65        if self.config.is_some() {
66            self.config.to_owned().unwrap()
67        } else {
68            NewConfig()
69        }
70    }
71
72    pub fn InitWithOptions(
73        &mut self,
74        regionId: &str,
75        config: &Config,
76        credential: AccessKeyCredential,
77    ) -> AliyunResult<()> {
78        let matched = Regex::new(r"^[a-zA-Z0-9_-]+$")
79            .expect("Regex parse failed")
80            .is_match(regionId);
81        if !matched {
82            return Err(AliyunSMSError(
83                "regionId contains invalid characters".to_string(),
84            ));
85        }
86        self.regionId = regionId.to_string();
87        self.config = Some(config.to_owned());
88        self.httpClient = http::Client::New();
89        self.signer = singers::NewSignerWithCredential(credential)?;
90        Ok(())
91    }
92    // smd 短信用的老接口,没使用这个函数,暂时不实现
93    pub fn ProcessCommonRequestWithSigner(request: http::Request) {
94        todo!()
95    }
96    pub fn DoAction(
97        &mut self,
98        request: &mut requests::AcsRequest,
99        response: &mut responses::AcsResponse,
100    ) -> AliyunResult<()> {
101        self.DoActionWithSigner(request, response, None)?;
102        Ok(())
103    }
104
105    pub fn DoActionWithSigner(
106        &self,
107        request: &mut AcsRequest,
108        response: &mut AcsResponse,
109        signer: Option<Box<dyn Signer>>,
110    ) -> AliyunResult<()> {
111        if !self.Network.is_empty() {
112            let matched = Regex::new(r"^[a-zA-Z0-9_-]+$")
113                .expect("newwork Regex parse failed")
114                .is_match(self.Network.as_str());
115            if !matched {
116                return Err(
117                    Error::new(ErrorKind::Other, "netWork contains invalid characters").into(),
118                );
119            }
120        }
121        if signer.is_none() {
122            let mut httpRequest =
123                self.buildRequestWithSigner(request, Some(Box::new(self.signer.to_owned())))?;
124            let mut httpClient = http::Client::New();
125            let httpResponse = httpClient.Do(&mut httpRequest)?;
126            debug!("httpResponse1: {:?}\n", httpResponse);
127            response.parseFromHttpResponse(&httpResponse);
128        } else {
129            let mut httpRequest = self.buildRequestWithSigner(request, signer)?;
130            let mut httpClient = http::Client::New();
131            let httpResponse = httpClient.Do(&mut httpRequest)?;
132            debug!("httpResponse2: {:?}\n", httpResponse);
133            response.parseFromHttpResponse(&httpResponse);
134        }
135        Ok(())
136    }
137    pub fn buildRequestWithSigner(
138        &self,
139
140        request: &mut AcsRequest,
141        signer: Option<Box<dyn Signer>>,
142    ) -> AliyunResult<http::Request> {
143        request.addHeaderParam("x-sdk-core-version", Version);
144        let mut regionId = self.regionId.to_owned();
145        if !request.GetRegionId().is_empty() {
146            regionId = request.GetRegionId().to_owned();
147        }
148        let mut endpoint = request.GetDomain().to_string();
149        if endpoint.is_empty() && !self.Domain.is_empty() {
150            endpoint = self.Domain.as_str().to_owned()
151        }
152        if endpoint.is_empty() {
153            endpoint = endpoints::GetEndpointFromMap(&regionId, request.GetProduct()).to_owned();
154        }
155        if endpoint.is_empty()
156            && !self.EndpointType.is_empty()
157            && (request.GetProduct() != "Sts" || request.GetQueryParams().is_empty())
158        {
159            if !self.EndpointMap.is_empty() && self.Network.is_empty() || self.Network == "public" {
160                endpoint = self
161                    .EndpointMap
162                    .get(&regionId)
163                    .map_or("".to_string(), |x| x.to_string())
164            }
165
166            if endpoint.is_empty() {
167                endpoint = self.GetEndpointRules(&regionId, request.GetProduct())?;
168            }
169        }
170
171        // if endpoint =="" {
172        //     let resolveParam=
173        // }
174        request.SetDomain(endpoint.as_str());
175        if request.GetScheme().is_empty() {
176            request.SetScheme(
177                self.config
178                    .as_ref()
179                    .expect("config is NONE")
180                    .Scheme
181                    .as_str(),
182            );
183        }
184        // init request params
185
186        let mut httpRequest: http::Request = buildHttpRequest(request, signer, &regionId)?;
187        let DefaultUserAgent: String = format!(
188            "AlibabaCloud ({}; {}) Rust/{} Core/{}",
189            OS, ARCH, "rustc/1.60.0", Version
190        );
191        let userAgent = DefaultUserAgent;
192        httpRequest.Header.Set("User-Agent", &userAgent);
193
194        Ok(httpRequest)
195    }
196
197    pub fn GetEndpointRules(&self, regionId: &str, product: &str) -> AliyunResult<String> {
198        let mut endpointRaw: String = String::new();
199        if self.EndpointType == "regional" {
200            if regionId.is_empty() {
201                return Err(AliyunSMSError(
202                    "RegionId is empty, please set a valid RegionId.".to_string(),
203                ));
204            }
205            endpointRaw = strings::Replace(
206                "<product><network>.<region_id>.aliyuncs.com",
207                "<region_id>",
208                regionId,
209                1,
210            );
211        } else {
212            endpointRaw = "<product><network>.aliyuncs.com".to_string();
213        };
214        endpointRaw = strings::Replace(endpointRaw, "<product>", strings::ToLower(product), 1);
215        if self.Network.is_empty() || self.Network == "public" {
216            endpointRaw = strings::Replace(endpointRaw, "<network>", "", 1);
217        } else {
218            endpointRaw = strings::Replace(
219                endpointRaw,
220                "<network>",
221                "-".to_owned() + self.Network.as_str(),
222                1,
223            )
224        }
225        Ok(endpointRaw)
226    }
227}
228
229fn buildHttpRequest(
230    request: &mut AcsRequest,
231    singer: Option<Box<dyn Signer>>,
232    regionId: &str,
233) -> AliyunResult<http::Request> {
234    Sign(request, singer, regionId)?;
235    let requestMethod = request.GetMethod();
236
237    let requestUrl = request.BuildUrl();
238    let body = request.GetBodyReader();
239    let mut httpReqeust =
240        http::Request::New(requestMethod, &requestUrl, Some(body.Bytes().into()))?;
241    for (key, value) in request.GetHeaders() {
242        httpReqeust.Header.Set(key, value);
243    }
244    debug!("httpRequest: {:?}\n", httpReqeust);
245    debug!("Headers: {:?}\n", httpReqeust.Header);
246    Ok(httpReqeust)
247}
248pub fn NewConfig() -> Config {
249    Config {
250        AutoRetry: false,
251        MaxRetryTime: 3,
252        UserAgent: "".to_string(),
253        Debug: false,
254        EnableAsync: false,
255        MaxTaskQueueSize: 1000,
256        GoRoutinePoolSize: 5,
257        Scheme: "HTTP".to_string(),
258    }
259}
260
261pub fn SetEndpointDataToClient(client: &mut Client) {
262    client.EndpointMap = GetEndpointMap();
263    client.EndpointType = GetEndpointType();
264}
265
266pub fn GetEndpointMap() -> HashMap<String, String> {
267    let mut EndpointMap = HashMap::new();
268    // 华北2(北京)
269    EndpointMap.insert(
270        "cn-beijing".to_string(),
271        "dysmsapi.aliyuncs.com".to_string(),
272    );
273
274    // 华北3(张家口)
275    EndpointMap.insert(
276        "cn-zhangjiakou".to_string(),
277        "dysmsapi.aliyuncs.com".to_string(),
278    );
279
280    // 华北5(呼和浩特)
281    EndpointMap.insert(
282        "cn-huhehaote".to_string(),
283        "dysmsapi.aliyuncs.com".to_string(),
284    );
285
286    // 华北6(乌兰察布)
287    EndpointMap.insert(
288        "cn-wulanchabu".to_string(),
289        "dysmsapi.aliyuncs.com".to_string(),
290    );
291
292    // 华东1(杭州)
293    EndpointMap.insert(
294        "cn-hangzhou".to_string(),
295        "dysmsapi.aliyuncs.com".to_string(),
296    );
297
298    // 华东2(上海)
299    EndpointMap.insert(
300        "cn-shanghai".to_string(),
301        "dysmsapi.aliyuncs.com".to_string(),
302    );
303
304    // 华南1(深圳)
305    EndpointMap.insert(
306        "cn-shenzhen".to_string(),
307        "dysmsapi.aliyuncs.com".to_string(),
308    );
309
310    // 西南1(成都)
311    EndpointMap.insert(
312        "cn-chengdu".to_string(),
313        "dysmsapi.aliyuncs.com".to_string(),
314    );
315
316    // 中国香港
317    EndpointMap.insert(
318        "cn-hongkong".to_string(),
319        "dysmsapi.aliyuncs.com".to_string(),
320    );
321
322    // 澳大利亚(悉尼)
323    EndpointMap.insert(
324        "ap-southeast-2".to_string(),
325        "dysmsapi.ap-southeast-1.aliyuncs.com".to_string(),
326    );
327
328    // 马来西亚(吉隆坡)
329    EndpointMap.insert(
330        "ap-southeast-3".to_string(),
331        "dysmsapi.ap-southeast-1.aliyuncs.com".to_string(),
332    );
333
334    // 日本(东京)
335    EndpointMap.insert(
336        "ap-northeast-1".to_string(),
337        "dysmsapi.ap-southeast-1.aliyuncs.com".to_string(),
338    );
339
340    // 新加坡
341    EndpointMap.insert(
342        "ap-southeast-1".to_string(),
343        "dysmsapi.ap-southeast-1.aliyuncs.com".to_string(),
344    );
345
346    // 德国(法兰克福)
347    EndpointMap.insert(
348        "eu-central-1".to_string(),
349        "dysmsapi.ap-southeast-1.aliyuncs.com".to_string(),
350    );
351
352    // 美国(弗吉尼亚)
353    EndpointMap.insert(
354        "us-east-1".to_string(),
355        "dysmsapi.ap-southeast-1.aliyuncs.com".to_string(),
356    );
357
358    // 美国(硅谷)
359    EndpointMap.insert(
360        "us-west-1".to_string(),
361        "dysmsapi.ap-southeast-1.aliyuncs.com".to_string(),
362    );
363
364    // 英国(伦敦)
365    EndpointMap.insert(
366        "eu-west-1".to_string(),
367        "dysmsapi.ap-southeast-1.aliyuncs.com".to_string(),
368    );
369
370    // 阿联酋(迪拜)
371    EndpointMap.insert(
372        "me-east-1".to_string(),
373        "dysmsapi.ap-southeast-1.aliyuncs.com".to_string(),
374    );
375
376    EndpointMap
377}
378
379pub fn GetEndpointType() -> String {
380    EndpointType.to_string()
381}
382
383// hookDo  等价于 golang 的http.client.Do 方法只是改了个名字。
384pub fn hookDo(
385    f: fn(req: &http::Request) -> AliyunResult<http::Response>,
386) -> fn(req: &http::Request) -> AliyunResult<http::Response> {
387    f
388}