http_types/auth/
authorization.rsuse crate::auth::AuthenticationScheme;
use crate::bail_status as bail;
use crate::headers::{HeaderName, HeaderValue, Headers, AUTHORIZATION};
#[derive(Debug)]
pub struct Authorization {
scheme: AuthenticationScheme,
credentials: String,
}
impl Authorization {
pub fn new(scheme: AuthenticationScheme, credentials: String) -> Self {
Self {
scheme,
credentials,
}
}
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
let headers = match headers.as_ref().get(AUTHORIZATION) {
Some(headers) => headers,
None => return Ok(None),
};
let value = headers.iter().last().unwrap();
let mut iter = value.as_str().splitn(2, ' ');
let scheme = iter.next();
let credential = iter.next();
let (scheme, credentials) = match (scheme, credential) {
(None, _) => bail!(400, "Could not find scheme"),
(Some(_), None) => bail!(400, "Could not find credentials"),
(Some(scheme), Some(credentials)) => (scheme.parse()?, credentials.to_owned()),
};
Ok(Some(Self {
scheme,
credentials,
}))
}
pub fn apply(&self, mut headers: impl AsMut<Headers>) {
headers.as_mut().insert(self.name(), self.value());
}
pub fn name(&self) -> HeaderName {
AUTHORIZATION
}
pub fn value(&self) -> HeaderValue {
let output = format!("{} {}", self.scheme, self.credentials);
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
}
pub fn scheme(&self) -> AuthenticationScheme {
self.scheme
}
pub fn set_scheme(&mut self, scheme: AuthenticationScheme) {
self.scheme = scheme;
}
pub fn credentials(&self) -> &str {
self.credentials.as_str()
}
pub fn set_credentials(&mut self, credentials: String) {
self.credentials = credentials;
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::headers::Headers;
#[test]
fn smoke() -> crate::Result<()> {
let scheme = AuthenticationScheme::Basic;
let credentials = "0xdeadbeef202020";
let authz = Authorization::new(scheme, credentials.into());
let mut headers = Headers::new();
authz.apply(&mut headers);
let authz = Authorization::from_headers(headers)?.unwrap();
assert_eq!(authz.scheme(), AuthenticationScheme::Basic);
assert_eq!(authz.credentials(), credentials);
Ok(())
}
#[test]
fn bad_request_on_parse_error() {
let mut headers = Headers::new();
headers.insert(AUTHORIZATION, "<nori ate the tag. yum.>");
let err = Authorization::from_headers(headers).unwrap_err();
assert_eq!(err.status(), 400);
}
}