use base64;
use Request;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HttpAuthCredentials {
pub login: String,
pub password: String,
}
pub fn basic_http_auth(request: &Request) -> Option<HttpAuthCredentials> {
let header = match request.header("Authorization") {
None => return None,
Some(h) => h,
};
let mut split = header.splitn(2, |c| c == ' ');
let authtype = match split.next() {
None => return None,
Some(t) => t,
};
if authtype != "Basic" {
return None;
}
let authvalue = match split.next().and_then(|val| base64::decode(val).ok()) {
Some(v) => v,
None => return None,
};
let mut split = authvalue.splitn(2, |&c| c == b':');
let login = match split
.next()
.map(Vec::from)
.and_then(|l| String::from_utf8(l).ok())
{
Some(l) => l,
None => return None,
};
let password = match split
.next()
.map(Vec::from)
.and_then(|p| String::from_utf8(p).ok())
{
Some(p) => p,
None => return None,
};
Some(HttpAuthCredentials { login, password })
}
#[cfg(test)]
mod test {
use super::basic_http_auth;
use super::HttpAuthCredentials;
use Request;
#[test]
fn basic_http_auth_no_header() {
let request = Request::fake_http("GET", "/", vec![], Vec::new());
assert_eq!(basic_http_auth(&request), None);
}
#[test]
fn basic_http_auth_wrong_header() {
let request = Request::fake_http(
"GET",
"/",
vec![("Authorization".to_owned(), "hello world".to_owned())],
Vec::new(),
);
assert_eq!(basic_http_auth(&request), None);
let request = Request::fake_http(
"GET",
"/",
vec![("Authorization".to_owned(), "Basic \0\0".to_owned())],
Vec::new(),
);
assert_eq!(basic_http_auth(&request), None);
}
#[test]
fn basic_http_auth_ok() {
let request = Request::fake_http(
"GET",
"/",
vec![(
"Authorization".to_owned(),
"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==".to_owned(),
)],
Vec::new(),
);
assert_eq!(
basic_http_auth(&request),
Some(HttpAuthCredentials {
login: "Aladdin".to_owned(),
password: "open sesame".to_owned(),
})
);
}
}