hyperx/header/common/
proxy_authorization.rs

1use std::any::Any;
2use std::fmt;
3use std::str::{FromStr, from_utf8};
4use std::ops::{Deref, DerefMut};
5use header::{Header, RawLike, Scheme};
6
7/// `Proxy-Authorization` header, defined in [RFC7235](https://tools.ietf.org/html/rfc7235#section-4.4)
8///
9/// The `Proxy-Authorization` header field allows a user agent to authenticate
10/// itself with an HTTP proxy -- usually, but not necessarily, after
11/// receiving a 407 (Proxy Authentication Required) response and the
12/// `Proxy-Authenticate` header. Its value consists of credentials containing
13/// the authentication information of the user agent for the realm of the
14/// resource being requested.
15///
16/// # ABNF
17///
18/// ```text
19/// Authorization = credentials
20/// ```
21///
22/// # Example values
23/// * `Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==`
24/// * `Bearer fpKL54jvWmEGVoRdCNjG`
25///
26/// # Examples
27///
28/// ```
29/// # extern crate http;
30/// use hyperx::header::{ProxyAuthorization, TypedHeaders};
31///
32/// let mut headers = http::HeaderMap::new();
33/// headers.encode(&ProxyAuthorization("let me in".to_owned()));
34/// ```
35/// ```
36/// # extern crate http;
37/// use hyperx::header::{ProxyAuthorization, Basic, TypedHeaders};
38///
39/// let mut headers = http::HeaderMap::new();
40/// headers.encode(
41///    &ProxyAuthorization(
42///        Basic {
43///            username: "Aladdin".to_owned(),
44///            password: Some("open sesame".to_owned())
45///        }
46///    )
47/// );
48/// ```
49///
50/// ```
51/// # extern crate http;
52/// use hyperx::header::{ProxyAuthorization, Bearer, TypedHeaders};
53///
54/// let mut headers = http::HeaderMap::new();
55/// headers.encode(
56///    &ProxyAuthorization(
57///        Bearer {
58///            token: "QWxhZGRpbjpvcGVuIHNlc2FtZQ".to_owned()
59///        }
60///    )
61/// );
62/// ```
63#[derive(Clone, PartialEq, Debug)]
64pub struct ProxyAuthorization<S: Scheme>(pub S);
65
66impl<S: Scheme> Deref for ProxyAuthorization<S> {
67    type Target = S;
68
69    fn deref(&self) -> &S {
70        &self.0
71    }
72}
73
74impl<S: Scheme> DerefMut for ProxyAuthorization<S> {
75    fn deref_mut(&mut self) -> &mut S {
76        &mut self.0
77    }
78}
79
80impl<S: Scheme + Any> Header for ProxyAuthorization<S> where <S as FromStr>::Err: 'static {
81    fn header_name() -> &'static str {
82        static NAME: &'static str = "Proxy-Authorization";
83        NAME
84    }
85
86    fn parse_header<'a, T>(raw: &'a T) -> ::Result<ProxyAuthorization<S>>
87    where T: RawLike<'a>
88    {
89        if let Some(line) = raw.one() {
90            let header = from_utf8(line)?;
91            if let Some(scheme) = <S as Scheme>::scheme() {
92                if header.starts_with(scheme) && header.len() > scheme.len() + 1 {
93                    match header[scheme.len() + 1..].parse::<S>().map(ProxyAuthorization) {
94                        Ok(h) => Ok(h),
95                        Err(_) => Err(::Error::Header)
96                    }
97                } else {
98                    Err(::Error::Header)
99                }
100            } else {
101                match header.parse::<S>().map(ProxyAuthorization) {
102                    Ok(h) => Ok(h),
103                    Err(_) => Err(::Error::Header)
104                }
105            }
106        } else {
107            Err(::Error::Header)
108        }
109    }
110
111    fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result {
112        f.fmt_line(self)
113    }
114}
115
116impl<S: Scheme> fmt::Display for ProxyAuthorization<S> {
117    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118        if let Some(scheme) = <S as Scheme>::scheme() {
119            write!(f, "{} ", scheme)?
120        };
121        self.0.fmt_scheme(f)
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use super::ProxyAuthorization;
128    use super::super::super::{Header, Raw, Basic, Bearer};
129
130    #[cfg(feature = "headers")]
131    use super::super::super::Headers;
132
133    #[cfg(feature = "headers")]
134    #[test]
135    fn test_raw_auth() {
136        let mut headers = Headers::new();
137        headers.set(ProxyAuthorization("foo bar baz".to_owned()));
138        assert_eq!(headers.to_string(), "Proxy-Authorization: foo bar baz\r\n".to_owned());
139    }
140
141    #[test]
142    fn test_raw_auth_parse() {
143        let r: Raw = b"foo bar baz".as_ref().into();
144        let header: ProxyAuthorization<String> = Header::parse_header(&r).unwrap();
145        assert_eq!(header.0, "foo bar baz");
146    }
147
148    #[cfg(feature = "headers")]
149    #[test]
150    fn test_basic_auth() {
151        let mut headers = Headers::new();
152        headers.set(ProxyAuthorization(
153            Basic { username: "Aladdin".to_owned(), password: Some("open sesame".to_owned()) }));
154        assert_eq!(
155            headers.to_string(),
156            "Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\r\n".to_owned());
157    }
158
159    #[cfg(feature = "headers")]
160    #[test]
161    fn test_basic_auth_no_password() {
162        let mut headers = Headers::new();
163        headers.set(ProxyAuthorization(Basic { username: "Aladdin".to_owned(), password: None }));
164        assert_eq!(headers.to_string(), "Proxy-Authorization: Basic QWxhZGRpbjo=\r\n".to_owned());
165    }
166
167    #[test]
168    fn test_basic_auth_parse() {
169        let r: Raw = b"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==".as_ref().into();
170        let auth: ProxyAuthorization<Basic> = Header::parse_header(&r).unwrap();
171        assert_eq!(auth.0.username, "Aladdin");
172        assert_eq!(auth.0.password, Some("open sesame".to_owned()));
173    }
174
175    #[test]
176    fn test_basic_auth_parse_no_password() {
177        let r: Raw = b"Basic QWxhZGRpbjo=".as_ref().into();
178        let auth: ProxyAuthorization<Basic> = Header::parse_header(&r).unwrap();
179        assert_eq!(auth.0.username, "Aladdin");
180        assert_eq!(auth.0.password, Some("".to_owned()));
181    }
182
183    #[cfg(feature = "headers")]
184    #[test]
185    fn test_bearer_auth() {
186        let mut headers = Headers::new();
187        headers.set(ProxyAuthorization(
188            Bearer { token: "fpKL54jvWmEGVoRdCNjG".to_owned() }));
189        assert_eq!(
190            headers.to_string(),
191            "Proxy-Authorization: Bearer fpKL54jvWmEGVoRdCNjG\r\n".to_owned());
192    }
193
194    #[test]
195    fn test_bearer_auth_parse() {
196        let r: Raw = b"Bearer fpKL54jvWmEGVoRdCNjG".as_ref().into();
197        let auth: ProxyAuthorization<Bearer> = Header::parse_header(&r).unwrap();
198        assert_eq!(auth.0.token, "fpKL54jvWmEGVoRdCNjG");
199    }
200}
201
202#[cfg(test)]
203#[cfg(feature = "nightly")]
204mod benches {
205    use super::ProxyAuthorization;
206    use ::header::{Basic, Bearer};
207
208    bench_header!(raw, ProxyAuthorization<String>, { vec![b"foo bar baz".to_vec()] });
209    bench_header!(basic, ProxyAuthorization<Basic>, { vec![b"Basic QWxhZGRpbjpuIHNlc2FtZQ==".to_vec()] });
210    bench_header!(bearer, ProxyAuthorization<Bearer>, { vec![b"Bearer fpKL54jvWmEGVoRdCNjG".to_vec()] });
211}
212
213impl<S> ::header::StandardHeader for ProxyAuthorization<S>
214    where S: Scheme + Any
215{
216    #[inline]
217    fn http_header_name() -> ::http::header::HeaderName {
218        ::http::header::PROXY_AUTHORIZATION
219    }
220}