Skip to content

Commit c93cdb2

Browse files
sfacklerseanmonstar
authored andcommitted
feat(headers): Implement ProxyAuthorization (#1394)
1 parent 95e0164 commit c93cdb2

File tree

2 files changed

+193
-0
lines changed

2 files changed

+193
-0
lines changed

src/header/common/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub use self::origin::Origin;
5050
pub use self::pragma::Pragma;
5151
pub use self::prefer::{Prefer, Preference};
5252
pub use self::preference_applied::PreferenceApplied;
53+
pub use self::proxy_authorization::ProxyAuthorization;
5354
pub use self::range::{Range, ByteRangeSpec};
5455
pub use self::referer::Referer;
5556
pub use self::referrer_policy::ReferrerPolicy;
@@ -485,6 +486,7 @@ mod origin;
485486
mod pragma;
486487
mod prefer;
487488
mod preference_applied;
489+
mod proxy_authorization;
488490
mod range;
489491
mod referer;
490492
mod referrer_policy;
+191
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
use std::any::Any;
2+
use std::fmt;
3+
use std::str::{FromStr, from_utf8};
4+
use std::ops::{Deref, DerefMut};
5+
use header::{Header, Raw, 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+
/// use hyper::header::{Headers, ProxyAuthorization};
30+
///
31+
/// let mut headers = Headers::new();
32+
/// headers.set(ProxyAuthorization("let me in".to_owned()));
33+
/// ```
34+
/// ```
35+
/// use hyper::header::{Headers, ProxyAuthorization, Basic};
36+
///
37+
/// let mut headers = Headers::new();
38+
/// headers.set(
39+
/// ProxyAuthorization(
40+
/// Basic {
41+
/// username: "Aladdin".to_owned(),
42+
/// password: Some("open sesame".to_owned())
43+
/// }
44+
/// )
45+
/// );
46+
/// ```
47+
///
48+
/// ```
49+
/// use hyper::header::{Headers, ProxyAuthorization, Bearer};
50+
///
51+
/// let mut headers = Headers::new();
52+
/// headers.set(
53+
/// ProxyAuthorization(
54+
/// Bearer {
55+
/// token: "QWxhZGRpbjpvcGVuIHNlc2FtZQ".to_owned()
56+
/// }
57+
/// )
58+
/// );
59+
/// ```
60+
#[derive(Clone, PartialEq, Debug)]
61+
pub struct ProxyAuthorization<S: Scheme>(pub S);
62+
63+
impl<S: Scheme> Deref for ProxyAuthorization<S> {
64+
type Target = S;
65+
66+
fn deref(&self) -> &S {
67+
&self.0
68+
}
69+
}
70+
71+
impl<S: Scheme> DerefMut for ProxyAuthorization<S> {
72+
fn deref_mut(&mut self) -> &mut S {
73+
&mut self.0
74+
}
75+
}
76+
77+
impl<S: Scheme + Any> Header for ProxyAuthorization<S> where <S as FromStr>::Err: 'static {
78+
fn header_name() -> &'static str {
79+
static NAME: &'static str = "Proxy-Authorization";
80+
NAME
81+
}
82+
83+
fn parse_header(raw: &Raw) -> ::Result<ProxyAuthorization<S>> {
84+
if let Some(line) = raw.one() {
85+
let header = try!(from_utf8(line));
86+
if let Some(scheme) = <S as Scheme>::scheme() {
87+
if header.starts_with(scheme) && header.len() > scheme.len() + 1 {
88+
match header[scheme.len() + 1..].parse::<S>().map(ProxyAuthorization) {
89+
Ok(h) => Ok(h),
90+
Err(_) => Err(::Error::Header)
91+
}
92+
} else {
93+
Err(::Error::Header)
94+
}
95+
} else {
96+
match header.parse::<S>().map(ProxyAuthorization) {
97+
Ok(h) => Ok(h),
98+
Err(_) => Err(::Error::Header)
99+
}
100+
}
101+
} else {
102+
Err(::Error::Header)
103+
}
104+
}
105+
106+
fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result {
107+
f.fmt_line(self)
108+
}
109+
}
110+
111+
impl<S: Scheme> fmt::Display for ProxyAuthorization<S> {
112+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113+
if let Some(scheme) = <S as Scheme>::scheme() {
114+
try!(write!(f, "{} ", scheme))
115+
};
116+
self.0.fmt_scheme(f)
117+
}
118+
}
119+
120+
#[cfg(test)]
121+
mod tests {
122+
use super::ProxyAuthorization;
123+
use super::super::super::{Headers, Header, Basic, Bearer};
124+
125+
#[test]
126+
fn test_raw_auth() {
127+
let mut headers = Headers::new();
128+
headers.set(ProxyAuthorization("foo bar baz".to_owned()));
129+
assert_eq!(headers.to_string(), "Proxy-Authorization: foo bar baz\r\n".to_owned());
130+
}
131+
132+
#[test]
133+
fn test_raw_auth_parse() {
134+
let header: ProxyAuthorization<String> = Header::parse_header(&b"foo bar baz".as_ref().into()).unwrap();
135+
assert_eq!(header.0, "foo bar baz");
136+
}
137+
138+
#[test]
139+
fn test_basic_auth() {
140+
let mut headers = Headers::new();
141+
headers.set(ProxyAuthorization(
142+
Basic { username: "Aladdin".to_owned(), password: Some("open sesame".to_owned()) }));
143+
assert_eq!(
144+
headers.to_string(),
145+
"Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\r\n".to_owned());
146+
}
147+
148+
#[test]
149+
fn test_basic_auth_no_password() {
150+
let mut headers = Headers::new();
151+
headers.set(ProxyAuthorization(Basic { username: "Aladdin".to_owned(), password: None }));
152+
assert_eq!(headers.to_string(), "Proxy-Authorization: Basic QWxhZGRpbjo=\r\n".to_owned());
153+
}
154+
155+
#[test]
156+
fn test_basic_auth_parse() {
157+
let auth: ProxyAuthorization<Basic> = Header::parse_header(
158+
&b"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==".as_ref().into()).unwrap();
159+
assert_eq!(auth.0.username, "Aladdin");
160+
assert_eq!(auth.0.password, Some("open sesame".to_owned()));
161+
}
162+
163+
#[test]
164+
fn test_basic_auth_parse_no_password() {
165+
let auth: ProxyAuthorization<Basic> = Header::parse_header(
166+
&b"Basic QWxhZGRpbjo=".as_ref().into()).unwrap();
167+
assert_eq!(auth.0.username, "Aladdin");
168+
assert_eq!(auth.0.password, Some("".to_owned()));
169+
}
170+
171+
#[test]
172+
fn test_bearer_auth() {
173+
let mut headers = Headers::new();
174+
headers.set(ProxyAuthorization(
175+
Bearer { token: "fpKL54jvWmEGVoRdCNjG".to_owned() }));
176+
assert_eq!(
177+
headers.to_string(),
178+
"Proxy-Authorization: Bearer fpKL54jvWmEGVoRdCNjG\r\n".to_owned());
179+
}
180+
181+
#[test]
182+
fn test_bearer_auth_parse() {
183+
let auth: ProxyAuthorization<Bearer> = Header::parse_header(
184+
&b"Bearer fpKL54jvWmEGVoRdCNjG".as_ref().into()).unwrap();
185+
assert_eq!(auth.0.token, "fpKL54jvWmEGVoRdCNjG");
186+
}
187+
}
188+
189+
bench_header!(raw, ProxyAuthorization<String>, { vec![b"foo bar baz".to_vec()] });
190+
bench_header!(basic, ProxyAuthorization<Basic>, { vec![b"Basic QWxhZGRpbjpuIHNlc2FtZQ==".to_vec()] });
191+
bench_header!(bearer, ProxyAuthorization<Bearer>, { vec![b"Bearer fpKL54jvWmEGVoRdCNjG".to_vec()] });

0 commit comments

Comments
 (0)