http_types/auth/
authorization.rs1use crate::auth::AuthenticationScheme;
2use crate::bail_status as bail;
3use crate::headers::{HeaderName, HeaderValue, Headers, AUTHORIZATION};
4
5#[derive(Debug)]
34pub struct Authorization {
35 scheme: AuthenticationScheme,
36 credentials: String,
37}
38
39impl Authorization {
40 pub fn new(scheme: AuthenticationScheme, credentials: String) -> Self {
42 Self {
43 scheme,
44 credentials,
45 }
46 }
47
48 pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
50 let headers = match headers.as_ref().get(AUTHORIZATION) {
51 Some(headers) => headers,
52 None => return Ok(None),
53 };
54
55 let value = headers.iter().last().unwrap();
58
59 let mut iter = value.as_str().splitn(2, ' ');
60 let scheme = iter.next();
61 let credential = iter.next();
62 let (scheme, credentials) = match (scheme, credential) {
63 (None, _) => bail!(400, "Could not find scheme"),
64 (Some(_), None) => bail!(400, "Could not find credentials"),
65 (Some(scheme), Some(credentials)) => (scheme.parse()?, credentials.to_owned()),
66 };
67
68 Ok(Some(Self {
69 scheme,
70 credentials,
71 }))
72 }
73
74 pub fn apply(&self, mut headers: impl AsMut<Headers>) {
76 headers.as_mut().insert(self.name(), self.value());
77 }
78
79 pub fn name(&self) -> HeaderName {
81 AUTHORIZATION
82 }
83
84 pub fn value(&self) -> HeaderValue {
86 let output = format!("{} {}", self.scheme, self.credentials);
87
88 unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
90 }
91
92 pub fn scheme(&self) -> AuthenticationScheme {
94 self.scheme
95 }
96
97 pub fn set_scheme(&mut self, scheme: AuthenticationScheme) {
99 self.scheme = scheme;
100 }
101
102 pub fn credentials(&self) -> &str {
104 self.credentials.as_str()
105 }
106
107 pub fn set_credentials(&mut self, credentials: String) {
109 self.credentials = credentials;
110 }
111}
112
113#[cfg(test)]
114mod test {
115 use super::*;
116 use crate::headers::Headers;
117
118 #[test]
119 fn smoke() -> crate::Result<()> {
120 let scheme = AuthenticationScheme::Basic;
121 let credentials = "0xdeadbeef202020";
122 let authz = Authorization::new(scheme, credentials.into());
123
124 let mut headers = Headers::new();
125 authz.apply(&mut headers);
126
127 let authz = Authorization::from_headers(headers)?.unwrap();
128
129 assert_eq!(authz.scheme(), AuthenticationScheme::Basic);
130 assert_eq!(authz.credentials(), credentials);
131 Ok(())
132 }
133
134 #[test]
135 fn bad_request_on_parse_error() {
136 let mut headers = Headers::new();
137 headers.insert(AUTHORIZATION, "<nori ate the tag. yum.>");
138 let err = Authorization::from_headers(headers).unwrap_err();
139 assert_eq!(err.status(), 400);
140 }
141}