alloy_transport/
common.rs1use base64::{engine::general_purpose, Engine};
2use std::fmt;
3
4#[derive(Clone, Debug, PartialEq, Eq)]
8pub enum Authorization {
9 Basic(String),
11 Bearer(String),
13 Raw(String),
15}
16
17impl Authorization {
18 pub fn extract_from_url(url: &url::Url) -> Option<Self> {
23 let username = url.username();
24 let password = url.password();
25
26 let has_userinfo = !username.is_empty() || password.is_some();
29 has_userinfo.then(|| Self::basic(username, password.unwrap_or_default()))
30 }
31
32 pub fn authority(auth: impl AsRef<str>) -> Self {
34 let auth_secret = general_purpose::STANDARD.encode(auth.as_ref());
35 Self::Basic(auth_secret)
36 }
37
38 pub fn basic(username: impl AsRef<str>, password: impl AsRef<str>) -> Self {
40 let username = username.as_ref();
41 let password = password.as_ref();
42 Self::authority(format!("{username}:{password}"))
43 }
44
45 pub fn bearer(token: impl Into<String>) -> Self {
47 Self::Bearer(token.into())
48 }
49
50 pub fn raw(token: impl Into<String>) -> Self {
52 Self::Raw(token.into())
53 }
54}
55
56impl fmt::Display for Authorization {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 match self {
59 Self::Basic(auth) => write!(f, "Basic {auth}"),
60 Self::Bearer(auth) => write!(f, "Bearer {auth}"),
61 Self::Raw(auth) => write!(f, "{auth}"),
62 }
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69 use url::Url;
70
71 #[test]
72 fn test_extract_from_url_with_basic_auth() {
73 let url = Url::parse("http://username:password@domain.com").unwrap();
74 let auth = Authorization::extract_from_url(&url).unwrap();
75
76 assert_eq!(
78 auth,
79 Authorization::Basic(general_purpose::STANDARD.encode("username:password"))
80 );
81 }
82
83 #[test]
84 fn test_extract_from_url_no_auth() {
85 let url = Url::parse("http://domain.com").unwrap();
86 assert!(Authorization::extract_from_url(&url).is_none());
87 }
88
89 #[test]
90 fn test_extract_from_url_with_localhost_username() {
91 let url = Url::parse("http://localhost:password@domain.com").unwrap();
93 let auth = Authorization::extract_from_url(&url).unwrap();
94 assert_eq!(
95 auth,
96 Authorization::Basic(general_purpose::STANDARD.encode("localhost:password"))
97 );
98 }
99
100 #[test]
101 fn test_extract_from_url_plain_host() {
102 let url = Url::parse("http://127.0.0.1:8080").unwrap();
104 assert!(Authorization::extract_from_url(&url).is_none());
105 }
106
107 #[test]
108 fn test_extract_from_url_password_only() {
109 let url = Url::parse("http://:secret@domain.com").unwrap();
110 let auth = Authorization::extract_from_url(&url).unwrap();
111 assert_eq!(auth, Authorization::Basic(general_purpose::STANDARD.encode(":secret")));
112 }
113
114 #[test]
115 fn test_authority() {
116 let auth = Authorization::authority("user:pass");
117 assert_eq!(auth, Authorization::Basic(general_purpose::STANDARD.encode("user:pass")));
118 }
119
120 #[test]
121 fn test_basic() {
122 let auth = Authorization::basic("user", "pass");
123 assert_eq!(auth, Authorization::Basic(general_purpose::STANDARD.encode("user:pass")));
124 }
125
126 #[test]
127 fn test_raw() {
128 let auth = Authorization::raw("raw_token");
129 assert_eq!(auth, Authorization::Raw("raw_token".to_string()));
130 }
131}