cogo_http/header/common/
authorization.rs1use std::any::Any;
2use std::fmt::{self, Display};
3use std::str::{FromStr, from_utf8};
4use std::ops::{Deref, DerefMut};
5use base64::{encode, decode};
6use crate::header::{Header, HeaderFormat};
7
8#[derive(Clone, PartialEq, Debug)]
58pub struct Authorization<S: Scheme>(pub S);
59
60impl<S: Scheme> Deref for Authorization<S> {
61 type Target = S;
62
63 fn deref(&self) -> &S {
64 &self.0
65 }
66}
67
68impl<S: Scheme> DerefMut for Authorization<S> {
69 fn deref_mut(&mut self) -> &mut S {
70 &mut self.0
71 }
72}
73
74impl<S: Scheme + Any> Header for Authorization<S> where <S as FromStr>::Err: 'static {
75 fn header_name() -> &'static str {
76 "Authorization"
77 }
78
79 fn parse_header(raw: &[Vec<u8>]) -> crate::Result<Authorization<S>> {
80 if raw.len() != 1 {
81 return Err(crate::Error::Header);
82 }
83 let header = r#try!(from_utf8(unsafe { &raw.get_unchecked(0)[..] }));
84 if let Some(scheme) = <S as Scheme>::scheme() {
85 if header.starts_with(scheme) && header.len() > scheme.len() + 1 {
86 match header[scheme.len() + 1..].parse::<S>().map(Authorization) {
87 Ok(h) => Ok(h),
88 Err(_) => Err(crate::Error::Header)
89 }
90 } else {
91 Err(crate::Error::Header)
92 }
93 } else {
94 match header.parse::<S>().map(Authorization) {
95 Ok(h) => Ok(h),
96 Err(_) => Err(crate::Error::Header)
97 }
98 }
99 }
100}
101
102impl<S: Scheme + Any> HeaderFormat for Authorization<S> where <S as FromStr>::Err: 'static {
103 fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
104 if let Some(scheme) = <S as Scheme>::scheme() {
105 r#try!(write!(f, "{} ", scheme))
106 };
107 self.0.fmt_scheme(f)
108 }
109}
110
111pub trait Scheme: FromStr + fmt::Debug + Clone + Send + Sync {
113 fn scheme() -> Option<&'static str>;
117 fn fmt_scheme(&self, _: &mut fmt::Formatter) -> fmt::Result;
119}
120
121impl Scheme for String {
122 fn scheme() -> Option<&'static str> {
123 None
124 }
125
126 fn fmt_scheme(&self, f: &mut fmt::Formatter) -> fmt::Result {
127 Display::fmt(self, f)
128 }
129}
130
131#[derive(Clone, PartialEq, Debug)]
133pub struct Basic {
134 pub username: String,
136 pub password: Option<String>
139}
140
141impl Scheme for Basic {
142 fn scheme() -> Option<&'static str> {
143 Some("Basic")
144 }
145
146 fn fmt_scheme(&self, f: &mut fmt::Formatter) -> fmt::Result {
147 let mut text = self.username.clone();
151 text.push(':');
152 if let Some(ref pass) = self.password {
153 text.push_str(&pass[..]);
154 }
155
156 f.write_str(&encode(text.as_bytes()))
157 }
158}
159
160impl FromStr for Basic {
161 type Err = crate::Error;
162 fn from_str(s: &str) -> crate::Result<Basic> {
163 match decode(s) {
164 Ok(decoded) => match String::from_utf8(decoded) {
165 Ok(text) => {
166 let parts = &mut text.split(':');
167 let user = match parts.next() {
168 Some(part) => part.to_owned(),
169 None => return Err(crate::Error::Header)
170 };
171 let password = match parts.next() {
172 Some(part) => Some(part.to_owned()),
173 None => None
174 };
175 Ok(Basic {
176 username: user,
177 password: password
178 })
179 },
180 Err(e) => {
181 debug!("Basic::from_utf8 error={:?}", e);
182 Err(crate::Error::Header)
183 }
184 },
185 Err(e) => {
186 debug!("Basic::from_base64 error={:?}", e);
187 Err(crate::Error::Header)
188 }
189 }
190 }
191}
192
193#[derive(Clone, PartialEq, Debug)]
194pub struct Bearer {
196 pub token: String
198}
199
200impl Scheme for Bearer {
201 fn scheme() -> Option<&'static str> {
202 Some("Bearer")
203 }
204
205 fn fmt_scheme(&self, f: &mut fmt::Formatter) -> fmt::Result {
206 write!(f, "{}", self.token)
207 }
208}
209
210impl FromStr for Bearer {
211 type Err = crate::Error;
212 fn from_str(s: &str) -> crate::Result<Bearer> {
213 Ok(Bearer { token: s.to_owned()})
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 use super::{Authorization, Basic, Bearer};
220 use super::super::super::{Headers, Header};
221
222 #[test]
223 fn test_raw_auth() {
224 let mut headers = Headers::new();
225 headers.set(Authorization("foo bar baz".to_owned()));
226 assert_eq!(headers.to_string(), "Authorization: foo bar baz\r\n".to_owned());
227 }
228
229 #[test]
230 fn test_raw_auth_parse() {
231 let header: Authorization<String> = Header::parse_header(
232 &[b"foo bar baz".to_vec()]).unwrap();
233 assert_eq!(header.0, "foo bar baz");
234 }
235
236 #[test]
237 fn test_basic_auth() {
238 let mut headers = Headers::new();
239 headers.set(Authorization(
240 Basic { username: "Aladdin".to_owned(), password: Some("open sesame".to_owned()) }));
241 assert_eq!(
242 headers.to_string(),
243 "Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\r\n".to_owned());
244 }
245
246 #[test]
247 fn test_basic_auth_no_password() {
248 let mut headers = Headers::new();
249 headers.set(Authorization(Basic { username: "Aladdin".to_owned(), password: None }));
250 assert_eq!(headers.to_string(), "Authorization: Basic QWxhZGRpbjo=\r\n".to_owned());
251 }
252
253 #[test]
254 fn test_basic_auth_parse() {
255 let auth: Authorization<Basic> = Header::parse_header(
256 &[b"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==".to_vec()]).unwrap();
257 assert_eq!(auth.0.username, "Aladdin");
258 assert_eq!(auth.0.password, Some("open sesame".to_owned()));
259 }
260
261 #[test]
262 fn test_basic_auth_parse_no_password() {
263 let auth: Authorization<Basic> = Header::parse_header(
264 &[b"Basic QWxhZGRpbjo=".to_vec()]).unwrap();
265 assert_eq!(auth.0.username, "Aladdin");
266 assert_eq!(auth.0.password, Some("".to_owned()));
267 }
268
269 #[test]
270 fn test_bearer_auth() {
271 let mut headers = Headers::new();
272 headers.set(Authorization(
273 Bearer { token: "fpKL54jvWmEGVoRdCNjG".to_owned() }));
274 assert_eq!(
275 headers.to_string(),
276 "Authorization: Bearer fpKL54jvWmEGVoRdCNjG\r\n".to_owned());
277 }
278
279 #[test]
280 fn test_bearer_auth_parse() {
281 let auth: Authorization<Bearer> = Header::parse_header(
282 &[b"Bearer fpKL54jvWmEGVoRdCNjG".to_vec()]).unwrap();
283 assert_eq!(auth.0.token, "fpKL54jvWmEGVoRdCNjG");
284 }
285}
286
287bench_header!(raw, Authorization<String>, { vec![b"foo bar baz".to_vec()] });
288bench_header!(basic, Authorization<Basic>, { vec![b"Basic QWxhZGRpbjpuIHNlc2FtZQ==".to_vec()] });
289bench_header!(bearer, Authorization<Bearer>, { vec![b"Bearer fpKL54jvWmEGVoRdCNjG".to_vec()] });