azure_rust/
errors.rs

1//! Client errors
2use std::io::Error as IoError;
3use std::time::Duration;
4
5use error_chain::*;
6use http::StatusCode;
7use reqwest::Error as ReqwestError;
8use serde::Deserialize;
9use serde_json::error::Error as SerdeError;
10use url::ParseError;
11
12
13error_chain! {
14    errors {
15        #[doc = "Client side error returned for faulty requests"]
16        Fault {
17            code: StatusCode,
18            error: ClientError,
19        } {
20            display("{}: '{}'", code, error.message)
21            description(error.message.as_str())
22          }
23        #[doc = "Error kind returned when a credential's rate limit has been exhausted. Wait for the reset duration before issuing more requests"]
24        RateLimit {
25            reset: Duration
26        } {
27            display("Rate limit exhausted. Will reset in {} seconds", reset.as_secs())
28        }
29    }
30    foreign_links {
31        Codec(SerdeError);
32        Reqwest(ReqwestError);
33        Url(ParseError);
34        IO(IoError);
35    }
36}
37
38// representations
39
40#[derive(Debug, Deserialize, PartialEq)]
41pub struct FieldErr {
42    pub resource: String,
43    pub field: Option<String>,
44    pub code: String,
45    pub message: Option<String>,
46    pub documentation_url: Option<String>,
47}
48
49#[derive(Debug, Deserialize, PartialEq)]
50pub struct ClientError {
51    pub message: String,
52    pub errors: Option<Vec<FieldErr>>,
53    pub documentation_url: Option<String>,
54}
55
56#[cfg(test)]
57mod tests {
58    use super::{ClientError, FieldErr};
59    use serde_json;
60    #[test]
61    fn deserialize_client_field_errors() {
62        for (json, expect) in vec![
63            // see https://github.com/softprops/hubcaps/issues/31
64            (
65                r#"{"message": "Validation Failed","errors":
66                [{
67                    "resource": "Release",
68                    "code": "custom",
69                    "message": "Published releases must have a valid tag"
70                }]}"#,
71                ClientError {
72                    message: "Validation Failed".to_owned(),
73                    errors: Some(vec![FieldErr {
74                        resource: "Release".to_owned(),
75                        code: "custom".to_owned(),
76                        field: None,
77                        message: Some(
78                            "Published releases \
79                             must have a valid tag"
80                                .to_owned(),
81                        ),
82                        documentation_url: None,
83                    }]),
84                    documentation_url: None,
85                },
86            ),
87        ] {
88            assert_eq!(serde_json::from_str::<ClientError>(json).unwrap(), expect);
89        }
90    }
91
92    #[test]
93    fn deserialize_client_top_level_documentation_url() {
94        let json = serde_json::json!({
95            "message": "Not Found",
96            "documentation_url": "https://developer.github.com/v3/activity/watching/#set-a-repository-subscription"
97        });
98        let expect = ClientError {
99            message: String::from("Not Found"),
100            errors: None,
101            documentation_url: Some(String::from(
102                "https://developer.github.com/v3/activity/watching/#set-a-repository-subscription",
103            )),
104        };
105        assert_eq!(serde_json::from_value::<ClientError>(json).unwrap(), expect)
106    }
107}