Skip to content

Commit 0b56c7f

Browse files
committed
feat(headers): support Opaque origin headers
Add support for Opaque origin header, serializing it to `null`. https://html.spec.whatwg.org/multipage/browsers.html#concept-origin Closes hyperium#1065
1 parent bb7c9b9 commit 0b56c7f

File tree

1 file changed

+52
-25
lines changed

1 file changed

+52
-25
lines changed

src/header/common/origin.rs

+52-25
Original file line numberDiff line numberDiff line change
@@ -31,41 +31,70 @@ use header::parsing::from_one_raw_str;
3131
/// );
3232
/// ```
3333
34-
#[derive(Clone, Debug)]
35-
pub struct Origin {
36-
/// The scheme, such as http or https
37-
scheme: Cow<'static,str>,
38-
/// The host, such as Host{hostname: "hyper.rs".to_owned(), port: None}
39-
host: Host,
34+
#[derive(PartialEq, Clone, Debug)]
35+
pub struct Origin(OriginOrNull);
36+
37+
#[derive(PartialEq, Clone, Debug)]
38+
enum OriginOrNull {
39+
Origin {
40+
/// The scheme, such as http or https
41+
scheme: Cow<'static,str>,
42+
/// The host, such as Host{hostname: "hyper.rs".to_owned(), port: None}
43+
host: Host,
44+
},
45+
Null,
4046
}
4147

4248
impl Origin {
4349
/// Creates a new `Origin` header.
4450
pub fn new<S: Into<Cow<'static,str>>, H: Into<Cow<'static,str>>>(scheme: S, hostname: H, port: Option<u16>) -> Origin{
45-
Origin {
51+
Origin(OriginOrNull::Origin {
4652
scheme: scheme.into(),
4753
host: Host::new(hostname, port),
54+
})
55+
}
56+
57+
/// Creates a `Null` `Origin` header.
58+
pub fn null() -> Origin {
59+
Origin(OriginOrNull::Null)
60+
}
61+
62+
/// Checks if `Origin` is `Null`.
63+
pub fn is_null(&self) -> bool {
64+
match self {
65+
&Origin(OriginOrNull::Null) => true,
66+
_ => false,
4867
}
4968
}
5069

5170
/// The scheme, such as http or https
5271
/// ```
5372
/// use hyper::header::Origin;
5473
/// let origin = Origin::new("https", "foo.com", Some(443));
55-
/// assert_eq!(origin.scheme(), "https");
74+
/// assert_eq!(origin.scheme(), Some("https"));
5675
/// ```
57-
pub fn scheme(&self) -> &str {
58-
&(self.scheme)
76+
#[allow(unused_variables)]
77+
// Variable `host` is considered unused, although there does not seem to be a way to omit it here.
78+
pub fn scheme(&self) -> Option<&str> {
79+
match self {
80+
&Origin(OriginOrNull::Origin { ref scheme, ref host }) => Some(&scheme),
81+
_ => None,
82+
}
5983
}
6084

6185
/// The host, such as Host{hostname: "hyper.rs".to_owned(), port: None}
6286
/// ```
6387
/// use hyper::header::{Origin,Host};
6488
/// let origin = Origin::new("https", "foo.com", Some(443));
65-
/// assert_eq!(origin.host(), &Host::new("foo.com", Some(443)));
89+
/// assert_eq!(origin.host(), Some(&Host::new("foo.com", Some(443))));
6690
/// ```
67-
pub fn host(&self) -> &Host {
68-
&(self.host)
91+
#[allow(unused_variables)]
92+
// Variable `scheme` is considered unused, although there does not seem to be a way to omit it here.
93+
pub fn host(&self) -> Option<&Host> {
94+
match self {
95+
&Origin(OriginOrNull::Origin { ref scheme, ref host }) => Some(&host),
96+
_ => None,
97+
}
6998
}
7099
}
71100

@@ -104,26 +133,24 @@ impl FromStr for Origin {
104133
s => Cow::Owned(s.to_owned())
105134
};
106135

107-
Ok(Origin{
136+
Ok(Origin(OriginOrNull::Origin {
108137
scheme: scheme,
109138
host: host
110-
})
139+
}))
111140
}
112141
}
113142

114143
impl fmt::Display for Origin {
115144
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116-
write!(f, "{}://{}", self.scheme, self.host)
117-
}
118-
}
119-
120-
impl PartialEq for Origin {
121-
fn eq(&self, other: &Origin) -> bool {
122-
self.scheme == other.scheme && self.host == other.host
145+
match self {
146+
&Origin(OriginOrNull::Origin { ref scheme, ref host }) => write!(f, "{}://{}", scheme, host),
147+
/// Serialized as "null" per ASCII serialization of an origin
148+
/// https://html.spec.whatwg.org/multipage/browsers.html#ascii-serialisation-of-an-origin
149+
_ => write!(f, "null")
150+
}
123151
}
124152
}
125153

126-
127154
#[cfg(test)]
128155
mod tests {
129156
use super::Origin;
@@ -143,11 +170,11 @@ mod tests {
143170
fn test_origin() {
144171
let origin : Origin = Header::parse_header(&vec![b"http://foo.com".to_vec()].into()).unwrap();
145172
assert_eq!(&origin, &Origin::new("http", "foo.com", None));
146-
assert_borrowed!(origin.scheme);
173+
assert_borrowed!(origin.scheme().unwrap().into());
147174

148175
let origin : Origin = Header::parse_header(&vec![b"https://foo.com:443".to_vec()].into()).unwrap();
149176
assert_eq!(&origin, &Origin::new("https", "foo.com", Some(443)));
150-
assert_borrowed!(origin.scheme);
177+
assert_borrowed!(origin.scheme().unwrap().into());
151178
}
152179
}
153180

0 commit comments

Comments
 (0)