hyperx/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 header::{Header, RawLike};
7
8#[derive(Clone, PartialEq, Debug)]
63pub struct Authorization<S: Scheme>(pub S);
64
65impl<S: Scheme> Deref for Authorization<S> {
66 type Target = S;
67
68 fn deref(&self) -> &S {
69 &self.0
70 }
71}
72
73impl<S: Scheme> DerefMut for Authorization<S> {
74 fn deref_mut(&mut self) -> &mut S {
75 &mut self.0
76 }
77}
78
79impl<S: Scheme + Any> Header for Authorization<S> where <S as FromStr>::Err: 'static {
80 fn header_name() -> &'static str {
81 static NAME: &'static str = "Authorization";
82 NAME
83 }
84
85 fn parse_header<'a, T>(raw: &'a T) -> ::Result<Authorization<S>>
86 where T: RawLike<'a>
87 {
88 if let Some(line) = raw.one() {
89 let header = from_utf8(line)?;
90 if let Some(scheme) = <S as Scheme>::scheme() {
91 if header.starts_with(scheme) && header.len() > scheme.len() + 1 {
92 match header[scheme.len() + 1..].parse::<S>().map(Authorization) {
93 Ok(h) => Ok(h),
94 Err(_) => Err(::Error::Header)
95 }
96 } else {
97 Err(::Error::Header)
98 }
99 } else {
100 match header.parse::<S>().map(Authorization) {
101 Ok(h) => Ok(h),
102 Err(_) => Err(::Error::Header)
103 }
104 }
105 } else {
106 Err(::Error::Header)
107 }
108 }
109
110 fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result {
111 f.fmt_line(self)
112 }
113}
114
115impl<S: Scheme> fmt::Display for Authorization<S> {
116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117 if let Some(scheme) = <S as Scheme>::scheme() {
118 write!(f, "{} ", scheme)?;
119 };
120 self.0.fmt_scheme(f)
121 }
122}
123
124pub trait Scheme: FromStr + fmt::Debug + Clone + Send + Sync {
126 fn scheme() -> Option<&'static str>;
130 fn fmt_scheme(&self, _: &mut fmt::Formatter) -> fmt::Result;
132}
133
134impl Scheme for String {
135 fn scheme() -> Option<&'static str> {
136 None
137 }
138
139 fn fmt_scheme(&self, f: &mut fmt::Formatter) -> fmt::Result {
140 Display::fmt(self, f)
141 }
142}
143
144#[derive(Clone, PartialEq, Debug)]
146pub struct Basic {
147 pub username: String,
149 pub password: Option<String>
153}
154
155impl Scheme for Basic {
156 fn scheme() -> Option<&'static str> {
157 Some("Basic")
158 }
159
160 fn fmt_scheme(&self, f: &mut fmt::Formatter) -> fmt::Result {
161 let mut text = self.username.clone();
165 text.push(':');
166 if let Some(ref pass) = self.password {
167 text.push_str(&pass[..]);
168 }
169
170 f.write_str(&encode(&text))
171 }
172}
173
174impl FromStr for Basic {
176 type Err = ::Error;
177 fn from_str(s: &str) -> ::Result<Basic> {
178 match decode(s) {
179 Ok(decoded) => match String::from_utf8(decoded) {
180 Ok(text) => {
181 let parts = &mut text.split(':');
182 let user = match parts.next() {
183 Some(part) => part.to_owned(),
184 None => return Err(::Error::Header)
185 };
186 let password = match parts.next() {
187 Some(part) => Some(part.to_owned()),
188 None => None
189 };
190 Ok(Basic {
191 username: user,
192 password: password
193 })
194 },
195 Err(_) => {
196 Err(::Error::Header)
197 }
198 },
199 Err(_) => {
200 Err(::Error::Header)
201 }
202 }
203 }
204}
205
206#[derive(Clone, PartialEq, Debug)]
207pub struct Bearer {
209 pub token: String
211}
212
213impl Scheme for Bearer {
214 fn scheme() -> Option<&'static str> {
215 Some("Bearer")
216 }
217
218 fn fmt_scheme(&self, f: &mut fmt::Formatter) -> fmt::Result {
219 write!(f, "{}", self.token)
220 }
221}
222
223impl FromStr for Bearer {
224 type Err = ::Error;
225 fn from_str(s: &str) -> ::Result<Bearer> {
226 Ok(Bearer { token: s.to_owned()})
227 }
228}
229
230#[cfg(test)]
231mod tests {
232 use super::{Authorization, Basic, Bearer};
233 use super::super::super::{Header, Raw};
234
235 #[cfg(feature = "headers")]
236 use super::super::super::Headers;
237
238 #[cfg(feature = "headers")]
239 #[test]
240 fn test_raw_auth() {
241 let mut headers = Headers::new();
242 headers.set(Authorization("foo bar baz".to_owned()));
243 assert_eq!(headers.to_string(), "Authorization: foo bar baz\r\n".to_owned());
244 }
245
246 #[test]
247 fn test_raw_auth_parse() {
248 let r: Raw = b"foo bar baz".as_ref().into();
249 let header: Authorization<String> = Header::parse_header(&r).unwrap();
250 assert_eq!(header.0, "foo bar baz");
251 }
252
253 #[cfg(feature = "headers")]
254 #[test]
255 fn test_basic_auth() {
256 let mut headers = Headers::new();
257 headers.set(Authorization(
258 Basic { username: "Aladdin".to_owned(), password: Some("open sesame".to_owned()) }));
259 assert_eq!(
260 headers.to_string(),
261 "Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\r\n".to_owned());
262 }
263
264 #[cfg(feature = "headers")]
265 #[test]
266 fn test_basic_auth_no_password() {
267 let mut headers = Headers::new();
268 headers.set(Authorization(Basic { username: "Aladdin".to_owned(), password: None }));
269 assert_eq!(headers.to_string(), "Authorization: Basic QWxhZGRpbjo=\r\n".to_owned());
270 }
271
272 #[test]
273 fn test_basic_auth_parse() {
274 let r: Raw = b"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==".as_ref().into();
275 let auth: Authorization<Basic> = Header::parse_header(&r).unwrap();
276 assert_eq!(auth.0.username, "Aladdin");
277 assert_eq!(auth.0.password, Some("open sesame".to_owned()));
278 }
279
280 #[test]
281 fn test_basic_auth_parse_no_password() {
282 let r: Raw = b"Basic QWxhZGRpbjo=".as_ref().into();
283 let auth: Authorization<Basic> = Header::parse_header(&r).unwrap();
284 assert_eq!(auth.0.username, "Aladdin");
285 assert_eq!(auth.0.password, Some("".to_owned()));
286 }
287
288 #[cfg(feature = "headers")]
289 #[test]
290 fn test_bearer_auth() {
291 let mut headers = Headers::new();
292 headers.set(Authorization(
293 Bearer { token: "fpKL54jvWmEGVoRdCNjG".to_owned() }));
294 assert_eq!(
295 headers.to_string(),
296 "Authorization: Bearer fpKL54jvWmEGVoRdCNjG\r\n".to_owned());
297 }
298
299 #[test]
300 fn test_bearer_auth_parse() {
301 let r: Raw = b"Bearer fpKL54jvWmEGVoRdCNjG".as_ref().into();
302 let auth: Authorization<Bearer> = Header::parse_header(&r).unwrap();
303 assert_eq!(auth.0.token, "fpKL54jvWmEGVoRdCNjG");
304 }
305}
306
307bench_header!(raw, Authorization<String>, { vec![b"foo bar baz".to_vec()] });
308bench_header!(basic, Authorization<Basic>, { vec![b"Basic QWxhZGRpbjpuIHNlc2FtZQ==".to_vec()] });
309bench_header!(bearer, Authorization<Bearer>, { vec![b"Bearer fpKL54jvWmEGVoRdCNjG".to_vec()] });
310
311impl<S> ::header::StandardHeader for Authorization<S>
312 where S: Scheme + Any
313{
314 #[inline]
315 fn http_header_name() -> ::http::header::HeaderName {
316 ::http::header::AUTHORIZATION
317 }
318}