rama_net/user/credentials/
proxy.rs1use super::{Basic, Bearer};
2use rama_core::error::{ErrorContext, OpaqueError};
3use std::borrow::Cow;
4
5#[cfg(feature = "http")]
6use rama_http_types::HeaderValue;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum ProxyCredential {
11 Basic(Basic),
13 Bearer(Bearer),
15}
16
17impl From<Basic> for ProxyCredential {
18 fn from(basic: Basic) -> Self {
19 Self::Basic(basic)
20 }
21}
22
23impl From<Bearer> for ProxyCredential {
24 fn from(bearer: Bearer) -> Self {
25 Self::Bearer(bearer)
26 }
27}
28
29impl ProxyCredential {
30 pub fn try_from_header_str(value: impl AsRef<str>) -> Result<Self, OpaqueError> {
33 let value = value.as_ref();
34 Basic::try_from_header_str(value)
35 .map(Into::into)
36 .or_else(|_| Bearer::try_from_header_str(value).map(Into::into))
37 .context("try to construct proxy credentials from header str")
38 }
39
40 pub fn try_from_clear_str(s: impl Into<Cow<'static, str>>) -> Result<Self, OpaqueError> {
42 let s: Cow<'static, str> = s.into();
43 if s.contains(':') {
44 Basic::try_from_clear_str(s.into_owned()).map(Into::into)
45 } else {
46 Bearer::try_from_clear_str(s).map(Into::into)
47 }
48 }
49
50 pub fn as_header_string(&self) -> String {
52 match self {
53 Self::Basic(basic) => basic.as_header_string(),
54 Self::Bearer(bearer) => bearer.as_header_string(),
55 }
56 }
57
58 #[cfg(feature = "http")]
59 pub fn as_header_value(&self) -> HeaderValue {
61 match self {
62 Self::Basic(basic) => basic.as_header_value(),
63 Self::Bearer(bearer) => bearer.as_header_value(),
64 }
65 }
66
67 pub fn as_clear_string(&self) -> String {
69 match self {
70 Self::Basic(basic) => basic.as_clear_string(),
71 Self::Bearer(bearer) => bearer.as_clear_string(),
72 }
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn proxy_credentials_clear_invalid() {
82 assert!(
83 ProxyCredential::try_from_clear_str("").is_err(),
84 "parse: empty",
85 );
86 }
87
88 enum Is {
89 Basic(&'static str),
90 Bearer(&'static str),
91 }
92
93 fn assert_is(proxy: ProxyCredential, expected: Is) {
94 match expected {
95 Is::Basic(value) => match proxy {
96 ProxyCredential::Bearer(other) => panic!(
97 "expected proxy bearer {} to be the basic credential: {}",
98 other.as_clear_string(),
99 value
100 ),
101 ProxyCredential::Basic(other) => assert_eq!(other.as_clear_string(), value),
102 },
103 Is::Bearer(value) => match proxy {
104 ProxyCredential::Basic(other) => panic!(
105 "expected proxy basic {} to be the bearer: {}",
106 other.as_clear_string(),
107 value
108 ),
109 ProxyCredential::Bearer(other) => assert_eq!(other.as_clear_string(), value),
110 },
111 }
112 }
113
114 #[test]
115 fn proxy_credentials_header_valid() {
116 for (s, expected) in [
117 (
118 "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
119 Is::Basic("Aladdin:open sesame"),
120 ),
121 ("Basic QWxhZGRpbjo=", Is::Basic("Aladdin:")),
122 ("Bearer QWxhZGRpbjo=", Is::Bearer("QWxhZGRpbjo=")),
123 ("Bearer foobar", Is::Bearer("foobar")),
124 ] {
125 let credential = ProxyCredential::try_from_header_str(s)
126 .unwrap_or_else(|_| panic!("invalid proxy credential header str: {s}"));
127 assert_eq!(s, credential.as_header_string());
128 assert_is(credential, expected);
129 }
130 }
131
132 #[test]
133 fn proxy_credentials_clear_valid() {
134 for (s, expected) in [
135 ("Aladdin:open sesame", Is::Basic("Aladdin:open sesame")),
136 ("Aladdin:", Is::Basic("Aladdin:")),
137 ("QWxhZGRpbjo=", Is::Bearer("QWxhZGRpbjo=")),
138 ("foobar", Is::Bearer("foobar")),
139 ] {
140 let credential = ProxyCredential::try_from_clear_str(s)
141 .unwrap_or_else(|_| panic!("invalid proxy credential clear str: {s}"));
142 assert_eq!(s, credential.as_clear_string());
143 assert_is(credential, expected);
144 }
145 }
146}