actix_web_httpauth/headers/authorization/scheme/
bearer.rs1use std::{borrow::Cow, fmt};
2
3use actix_web::{
4 http::header::{HeaderValue, InvalidHeaderValue, TryIntoHeaderValue},
5 web::{BufMut, BytesMut},
6};
7
8use crate::headers::authorization::{errors::ParseError, scheme::Scheme};
9
10#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
17pub struct Bearer {
18 token: Cow<'static, str>,
19}
20
21impl Bearer {
22 pub fn new<T>(token: T) -> Bearer
30 where
31 T: Into<Cow<'static, str>>,
32 {
33 Bearer {
34 token: token.into(),
35 }
36 }
37
38 pub fn token(&self) -> &str {
40 self.token.as_ref()
41 }
42}
43
44impl Scheme for Bearer {
45 fn parse(header: &HeaderValue) -> Result<Self, ParseError> {
46 if header.len() < 8 {
48 return Err(ParseError::Invalid);
49 }
50
51 let mut parts = header.to_str()?.splitn(2, ' ');
52
53 match parts.next() {
54 Some("Bearer") => {}
55 _ => return Err(ParseError::MissingScheme),
56 }
57
58 let token = parts.next().ok_or(ParseError::Invalid)?;
59
60 Ok(Bearer {
61 token: token.to_string().into(),
62 })
63 }
64}
65
66impl fmt::Debug for Bearer {
67 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68 f.write_fmt(format_args!("Bearer ******"))
69 }
70}
71
72impl fmt::Display for Bearer {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 f.write_fmt(format_args!("Bearer {}", self.token))
75 }
76}
77
78impl TryIntoHeaderValue for Bearer {
79 type Error = InvalidHeaderValue;
80
81 fn try_into_value(self) -> Result<HeaderValue, Self::Error> {
82 let mut buffer = BytesMut::with_capacity(7 + self.token.len());
83 buffer.put(&b"Bearer "[..]);
84 buffer.extend_from_slice(self.token.as_bytes());
85
86 HeaderValue::from_maybe_shared(buffer.freeze())
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_parse_header() {
96 let value = HeaderValue::from_static("Bearer mF_9.B5f-4.1JqM");
97 let scheme = Bearer::parse(&value);
98
99 assert!(scheme.is_ok());
100 let scheme = scheme.unwrap();
101 assert_eq!(scheme.token, "mF_9.B5f-4.1JqM");
102 }
103
104 #[test]
105 fn test_empty_header() {
106 let value = HeaderValue::from_static("");
107 let scheme = Bearer::parse(&value);
108
109 assert!(scheme.is_err());
110 }
111
112 #[test]
113 fn test_wrong_scheme() {
114 let value = HeaderValue::from_static("OAuthToken foo");
115 let scheme = Bearer::parse(&value);
116
117 assert!(scheme.is_err());
118 }
119
120 #[test]
121 fn test_missing_token() {
122 let value = HeaderValue::from_static("Bearer ");
123 let scheme = Bearer::parse(&value);
124
125 assert!(scheme.is_err());
126 }
127
128 #[test]
129 fn test_into_header_value() {
130 let bearer = Bearer::new("mF_9.B5f-4.1JqM");
131
132 let result = bearer.try_into_value();
133 assert!(result.is_ok());
134 assert_eq!(
135 result.unwrap(),
136 HeaderValue::from_static("Bearer mF_9.B5f-4.1JqM")
137 );
138 }
139}