1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
extern crate reqwest;
extern crate base64;
#[macro_use] extern crate hyper;
#[macro_use] extern crate serde_derive;
extern crate serde;
extern crate serde_json;
extern crate sha1;
extern crate url;
pub mod api;
pub mod engine;
use std::fmt;
use std::io::Read;
#[derive(Debug)]
pub enum B2Error {
ReqwestError(reqwest::Error),
IOError(std::io::Error),
SerdeError(serde_json::Error),
B2Error(B2ApiError),
B2EngineError,
}
impl B2Error {
fn from_string(error: &str) -> B2Error {
let deserialized: B2ApiError = match serde_json::from_str(error) {
Ok(v) => v,
Err(e) => return B2Error::SerdeError(e)
};
B2Error::B2Error(deserialized)
}
fn from_response(mut resp: reqwest::Response) -> B2Error {
let mut res = String::new();
match resp.read_to_string(&mut res) {
Err(e) => return B2Error::IOError(e),
_ => ()
}
B2Error::from_string(&res)
}
}
fn handle_b2error_kinds(n: &str) -> B2Error {
let _b2err: B2ApiError = match serde_json::from_str(&n) {
Ok(v) => return B2Error::B2Error(v),
Err(e) => return B2Error::SerdeError(e),
};
}
#[derive(Deserialize, Serialize)]
pub struct B2ApiError {
pub status: u16,
pub code: String,
pub message: String
}
impl fmt::Debug for B2ApiError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "B2ApiError: error code {} - {}. Message: {}",self.status, self.code, self.message)
}
}
impl fmt::Display for B2ApiError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "A B2 API Error occurred. Error code {} - {}. Error message: {}",self.status, self.code, self.message)
}
}
impl std::error::Error for B2ApiError {
fn description(&self) -> &str {
"An error caused by some B2 API issue"
}
fn cause(&self) -> Option<&std::error::Error> {
None
}
}
#[cfg(test)]
mod tests {
pub const TEST_CREDENTIALS_FILE: &str = "credentials";
pub const TEST_BUCKET_ID: &str = "4663eedc6289033066000e13";
use B2Error;
#[test]
fn test_json_to_api_error() {
let json = r#"{
"code": "bad_auth_token",
"message": "Invalid authorization token",
"status": 401
}"#;
let err = match B2Error::from_string(&json) {
B2Error::B2Error(b2_api_error) => Ok(b2_api_error),
_ => Err("B2Error is not a B2Error::B2Error")
}.unwrap();
assert_eq!("bad_auth_token", err.code);
assert_eq!("Invalid authorization token", err.message);
assert_eq!(401, err.status);
}
use api::auth;
use reqwest;
#[test]
fn test_invalid_auth_returns_api_error(){
let client = reqwest::Client::new();
let response = auth::authenticate(&client, "");
match response {
Ok(_b2_auth) => (),
Err(b2_error) => {
match b2_error {
B2Error::B2Error(err) => {
assert_eq!("unauthorized", err.code);
assert_eq!(401, err.status);
}
_ => assert!(false)
}
}
}
}
}