Skip to content

Commit

Permalink
feat(headers): support Opaque origin headers (#1147)
Browse files Browse the repository at this point in the history
Add support for Opaque origin header, serializing it to `null`.
https://html.spec.whatwg.org/multipage/browsers.html#concept-origin

Closes #1065

BREAKING CHANGE: `Origin.scheme` and `Origin.host` now return `Option`s,
  since the `Origin` could be `null`.
  • Loading branch information
alexeyzab authored and seanmonstar committed Apr 24, 2017
1 parent 1cd8ea3 commit 4148599
Showing 1 changed file with 48 additions and 25 deletions.
73 changes: 48 additions & 25 deletions src/header/common/origin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,41 +31,66 @@ use header::parsing::from_one_raw_str;
/// );
/// ```
#[derive(Clone, Debug)]
pub struct Origin {
/// The scheme, such as http or https
scheme: Cow<'static,str>,
/// The host, such as Host{hostname: "hyper.rs".to_owned(), port: None}
host: Host,
#[derive(PartialEq, Clone, Debug)]
pub struct Origin(OriginOrNull);

#[derive(PartialEq, Clone, Debug)]
enum OriginOrNull {
Origin {
/// The scheme, such as http or https
scheme: Cow<'static,str>,
/// The host, such as Host{hostname: "hyper.rs".to_owned(), port: None}
host: Host,
},
Null,
}

impl Origin {
/// Creates a new `Origin` header.
pub fn new<S: Into<Cow<'static,str>>, H: Into<Cow<'static,str>>>(scheme: S, hostname: H, port: Option<u16>) -> Origin{
Origin {
Origin(OriginOrNull::Origin {
scheme: scheme.into(),
host: Host::new(hostname, port),
})
}

/// Creates a `Null` `Origin` header.
pub fn null() -> Origin {
Origin(OriginOrNull::Null)
}

/// Checks if `Origin` is `Null`.
pub fn is_null(&self) -> bool {
match self {
&Origin(OriginOrNull::Null) => true,
_ => false,
}
}

/// The scheme, such as http or https
/// ```
/// use hyper::header::Origin;
/// let origin = Origin::new("https", "foo.com", Some(443));
/// assert_eq!(origin.scheme(), "https");
/// assert_eq!(origin.scheme(), Some("https"));
/// ```
pub fn scheme(&self) -> &str {
&(self.scheme)
pub fn scheme(&self) -> Option<&str> {
match self {
&Origin(OriginOrNull::Origin { ref scheme, .. }) => Some(&scheme),
_ => None,
}
}

/// The host, such as Host{hostname: "hyper.rs".to_owned(), port: None}
/// ```
/// use hyper::header::{Origin,Host};
/// let origin = Origin::new("https", "foo.com", Some(443));
/// assert_eq!(origin.host(), &Host::new("foo.com", Some(443)));
/// assert_eq!(origin.host(), Some(&Host::new("foo.com", Some(443))));
/// ```
pub fn host(&self) -> &Host {
&(self.host)
pub fn host(&self) -> Option<&Host> {
match self {
&Origin(OriginOrNull::Origin { ref host, .. }) => Some(&host),
_ => None,
}
}
}

Expand Down Expand Up @@ -104,26 +129,24 @@ impl FromStr for Origin {
s => Cow::Owned(s.to_owned())
};

Ok(Origin{
Ok(Origin(OriginOrNull::Origin {
scheme: scheme,
host: host
})
}))
}
}

impl fmt::Display for Origin {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}://{}", self.scheme, self.host)
}
}

impl PartialEq for Origin {
fn eq(&self, other: &Origin) -> bool {
self.scheme == other.scheme && self.host == other.host
match self {
&Origin(OriginOrNull::Origin { ref scheme, ref host }) => write!(f, "{}://{}", scheme, host),
/// Serialized as "null" per ASCII serialization of an origin
/// https://html.spec.whatwg.org/multipage/browsers.html#ascii-serialisation-of-an-origin
_ => write!(f, "null")
}
}
}


#[cfg(test)]
mod tests {
use super::Origin;
Expand All @@ -143,11 +166,11 @@ mod tests {
fn test_origin() {
let origin : Origin = Header::parse_header(&vec![b"http://foo.com".to_vec()].into()).unwrap();
assert_eq!(&origin, &Origin::new("http", "foo.com", None));
assert_borrowed!(origin.scheme);
assert_borrowed!(origin.scheme().unwrap().into());

let origin : Origin = Header::parse_header(&vec![b"https://foo.com:443".to_vec()].into()).unwrap();
assert_eq!(&origin, &Origin::new("https", "foo.com", Some(443)));
assert_borrowed!(origin.scheme);
assert_borrowed!(origin.scheme().unwrap().into());
}
}

Expand Down

0 comments on commit 4148599

Please sign in to comment.