1#![deny(missing_docs,
4 missing_debug_implementations, missing_copy_implementations,
5 trivial_casts, trivial_numeric_casts,
6 unstable_features, unsafe_code,
7 unused_import_braces, unused_qualifications)]
8
9use std::env;
11
12use reqwest;
14use roxmltree;
15
16pub mod address;
18
19const SECURE_ENDPOINT: &'static str = "https://secure.shippingapis.com/ShippingAPI.dll?API=";
21const UNSECURE_ENDPOINT: &'static str = "http://production.shippingapis.com/ShippingAPI.dll?API=";
22
23const ENV_USER_ID: &'static str = "USPS_USER_ID";
24const ENV_PASSWORD: &'static str = "USPS_PASSWORD";
25
26#[derive(Debug, PartialEq)]
28pub struct USPSWebTool {
29 secure: bool,
30 user_id: String,
31 password: String,
32}
33
34impl USPSWebTool {
36 pub fn init(user_id: &str, password: &str) -> Self {
43 USPSWebTool {
44 secure: true,
45 user_id: String::from(user_id),
46 password: String::from(password)
47 }
48 }
49
50 pub fn new() -> Result<Self, env::VarError> {
63 let user_id = env::var(ENV_USER_ID)?;
64 let password = env::var(ENV_PASSWORD)?;
65
66 Ok(USPSWebTool {
67 secure: true,
68 user_id,
69 password,
70 })
71 }
72
73 pub fn use_http(mut self) -> Self {
82 self.secure = false;
83 self
84 }
85
86 pub fn verify_address(&self, address: address::USPSAddress) -> Result<address::USPSAddress, Box<dyn std::error::Error>> {
88 let mut req;
89 if self.secure {
90 req = String::from(SECURE_ENDPOINT);
91 } else {
92 req = String::from(UNSECURE_ENDPOINT);
93 }
94
95 req.push_str("Verify&XML=");
97 req.push_str(&format!("<AddressValidateRequest USERID=\"{}\"><Revision>1</Revision>", self.user_id));
98 req.push_str(&address.xml());
99 req.push_str("</AddressValidateRequest>");
100
101 let body = reqwest::get(&req)?.text()?;
103 println!("{:?}", body);
104
105 let xml = roxmltree::Document::parse(&body)?;
107 Ok(address::USPSAddress::from_xml(xml))
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 const DUMMY_UN: &'static str = "USERNAME";
119 const DUMMY_PW: &'static str = "PASSWORD";
120
121 #[test]
122 fn init_constructor() {
123 let dummy_struct = USPSWebTool {
124 secure: true,
125 user_id: String::from(DUMMY_UN),
126 password: String::from(DUMMY_PW),
127 };
128
129 assert_eq!(USPSWebTool::init(DUMMY_UN, DUMMY_PW), dummy_struct);
130 }
131
132 #[test]
133 fn new_constructor() {
134 env::set_var(ENV_USER_ID, DUMMY_UN);
135 env::set_var(ENV_PASSWORD, DUMMY_PW);
136
137 let dummy_struct = USPSWebTool {
138 secure: true,
139 user_id: String::from(DUMMY_UN),
140 password: String::from(DUMMY_PW),
141 };
142
143 assert_eq!(USPSWebTool::new().unwrap(), dummy_struct);
144 }
145
146 #[test]
147 #[should_panic]
148 fn new_contructor_no_env() {
149 env::remove_var(ENV_USER_ID);
150 env::remove_var(ENV_PASSWORD);
151
152 let dummy_struct = USPSWebTool {
153 secure: true,
154 user_id: String::from(DUMMY_UN),
155 password: String::from(DUMMY_PW),
156 };
157
158 assert_eq!(USPSWebTool::new().unwrap(), dummy_struct);
159 }
160
161 #[test]
162 fn use_http() {
163 let dummy_struct = USPSWebTool {
164 secure: false,
165 user_id: String::from(DUMMY_UN),
166 password: String::from(DUMMY_PW),
167 };
168
169 assert_eq!(USPSWebTool::init(DUMMY_UN, DUMMY_PW).use_http(),
170 dummy_struct);
171 }
172
173 mod address_test {
174 use super::*;
175
176 #[test]
177 fn test_address_1() {
178
179 let api = USPSWebTool::init("348XVRQT1293", "088NI00MI876");
180 let home = address::USPSAddress::quick("429 2nd Ave W", "104", "Seattle", "WA", "98119");
181 api.verify_address(home).unwrap();
182
183
184 }
185 }
186}
187