feat(headers): support Opaque origin headers (#1147)
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`.
This commit is contained in:
committed by
Sean McArthur
parent
1cd8ea36f3
commit
414859978b
@@ -31,20 +31,39 @@ use header::parsing::from_one_raw_str;
|
|||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub struct Origin {
|
pub struct Origin(OriginOrNull);
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
|
enum OriginOrNull {
|
||||||
|
Origin {
|
||||||
/// The scheme, such as http or https
|
/// The scheme, such as http or https
|
||||||
scheme: Cow<'static,str>,
|
scheme: Cow<'static,str>,
|
||||||
/// The host, such as Host{hostname: "hyper.rs".to_owned(), port: None}
|
/// The host, such as Host{hostname: "hyper.rs".to_owned(), port: None}
|
||||||
host: Host,
|
host: Host,
|
||||||
|
},
|
||||||
|
Null,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Origin {
|
impl Origin {
|
||||||
/// Creates a new `Origin` header.
|
/// 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{
|
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(),
|
scheme: scheme.into(),
|
||||||
host: Host::new(hostname, port),
|
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,20 +71,26 @@ impl Origin {
|
|||||||
/// ```
|
/// ```
|
||||||
/// use hyper::header::Origin;
|
/// use hyper::header::Origin;
|
||||||
/// let origin = Origin::new("https", "foo.com", Some(443));
|
/// 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 {
|
pub fn scheme(&self) -> Option<&str> {
|
||||||
&(self.scheme)
|
match self {
|
||||||
|
&Origin(OriginOrNull::Origin { ref scheme, .. }) => Some(&scheme),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The host, such as Host{hostname: "hyper.rs".to_owned(), port: None}
|
/// The host, such as Host{hostname: "hyper.rs".to_owned(), port: None}
|
||||||
/// ```
|
/// ```
|
||||||
/// use hyper::header::{Origin,Host};
|
/// use hyper::header::{Origin,Host};
|
||||||
/// let origin = Origin::new("https", "foo.com", Some(443));
|
/// 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 {
|
pub fn host(&self) -> Option<&Host> {
|
||||||
&(self.host)
|
match self {
|
||||||
|
&Origin(OriginOrNull::Origin { ref host, .. }) => Some(&host),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,26 +129,24 @@ impl FromStr for Origin {
|
|||||||
s => Cow::Owned(s.to_owned())
|
s => Cow::Owned(s.to_owned())
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Origin{
|
Ok(Origin(OriginOrNull::Origin {
|
||||||
scheme: scheme,
|
scheme: scheme,
|
||||||
host: host
|
host: host
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Origin {
|
impl fmt::Display for Origin {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}://{}", self.scheme, self.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")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Origin {
|
|
||||||
fn eq(&self, other: &Origin) -> bool {
|
|
||||||
self.scheme == other.scheme && self.host == other.host
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Origin;
|
use super::Origin;
|
||||||
@@ -143,11 +166,11 @@ mod tests {
|
|||||||
fn test_origin() {
|
fn test_origin() {
|
||||||
let origin : Origin = Header::parse_header(&vec![b"http://foo.com".to_vec()].into()).unwrap();
|
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_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();
|
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_eq!(&origin, &Origin::new("https", "foo.com", Some(443)));
|
||||||
assert_borrowed!(origin.scheme);
|
assert_borrowed!(origin.scheme().unwrap().into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user