Skip to main content

ali_oss_rs/
error.rs

1use std::fmt::Display;
2
3use thiserror::Error;
4
5//
6// Aliyun OSS API error response
7//
8// ```xml
9// <?xml version="1.0" ?>
10// <Error xmlns=”http://doc.oss-cn-hangzhou.aliyuncs.com”>
11//   <Code>MalformedXML</Code>
12//   <Message>The XML you provided was not well-formed or did not validate against our published schema.</Message>
13//   <RequestId>57ABD896CCB80C366955****</RequestId>
14//   <HostId>oss-cn-hangzhou.aliyuncs.com</HostId>
15//   <EC>0031-00000001</EC>
16//   <RecommendDoc>https://api.aliyun.com/troubleshoot?q=0031-00000001</RecommendDoc>
17// </Error>
18// ```
19#[derive(Debug, Default)]
20#[cfg_attr(feature = "serde-support", derive(serde::Serialize, serde::Deserialize))]
21#[cfg_attr(feature = "serde-camelcase", serde(rename_all = "camelCase"))]
22pub struct ErrorResponse {
23    pub code: String,
24    pub message: String,
25    pub request_id: String,
26    pub host_id: String,
27    pub ec: String,
28    pub recommend_doc: String,
29}
30
31impl ErrorResponse {
32    pub fn from_xml(xml_content: &str) -> crate::Result<Self> {
33        let mut reader = quick_xml::Reader::from_str(xml_content);
34        let mut ret = Self::default();
35
36        let mut current_tag = String::new();
37
38        loop {
39            match reader.read_event()? {
40                quick_xml::events::Event::Eof => break,
41
42                quick_xml::events::Event::Start(e) => {
43                    current_tag = String::from_utf8_lossy(e.local_name().as_ref()).to_string();
44                }
45
46                quick_xml::events::Event::Text(t) => match current_tag.as_str() {
47                    "Code" => ret.code = String::from_utf8_lossy(t.as_ref()).to_string(),
48                    "Message" => ret.message = String::from_utf8_lossy(t.as_ref()).to_string(),
49                    "RequestId" => ret.request_id = String::from_utf8_lossy(t.as_ref()).to_string(),
50                    "HostId" => ret.host_id = String::from_utf8_lossy(t.as_ref()).to_string(),
51                    "EC" => ret.ec = String::from_utf8_lossy(t.as_ref()).to_string(),
52                    "RecommendDoc" => ret.recommend_doc = String::from_utf8_lossy(t.as_ref()).to_string(),
53                    _ => {}
54                },
55
56                quick_xml::events::Event::End(_) => {
57                    current_tag.clear();
58                }
59
60                _ => {}
61            }
62        }
63
64        Ok(ret)
65    }
66}
67
68impl Display for ErrorResponse {
69    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70        write!(f, "Code: {}, Message: {}, Request Id: {}", self.code, self.message, self.request_id)
71    }
72}
73
74#[derive(Error, Debug)]
75pub enum Error {
76    #[error("{0}")]
77    InvalidHeaderName(#[from] reqwest::header::InvalidHeaderName),
78
79    #[error("{0}")]
80    InvalidHeaderValue(#[from] reqwest::header::InvalidHeaderValue),
81
82    #[error("{0}")]
83    UrlParseError(#[from] url::ParseError),
84
85    #[error("{0}")]
86    ReqwestError(#[from] reqwest::Error),
87
88    #[error("{0}")]
89    XmlParseError(#[from] quick_xml::Error),
90
91    #[error("{0}")]
92    ApiError(Box<ErrorResponse>),
93
94    #[error("{0}")]
95    IoError(#[from] std::io::Error),
96
97    #[error("{0}")]
98    FromUtf8Error(#[from] std::string::FromUtf8Error),
99
100    #[error("{0}")]
101    ParseIntError(#[from] std::num::ParseIntError),
102
103    #[error("{0}")]
104    StatusError(reqwest::StatusCode),
105
106    #[error("{0}")]
107    SerdeJsonError(#[from] serde_json::Error),
108
109    #[error("{0}")]
110    DecodeError(#[from] base64::DecodeError),
111
112    #[error("{0}")]
113    Other(String),
114}