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