From 5e3417145ced116147ef1e890b4f1e7c775ad173 Mon Sep 17 00:00:00 2001 From: Pyfisch Date: Sun, 3 May 2015 11:17:12 +0200 Subject: [PATCH] feat(headers): Allow `null` value in Access-Control-Allow-Origin The spec says the header can be either a `*`, `null` or an URL. Improve docs of header. BREAKING CHANGE: Add variant to Access-Control-Allow-Origin enum --- .../common/access_control_allow_origin.rs | 57 ++++++++++++------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/src/header/common/access_control_allow_origin.rs b/src/header/common/access_control_allow_origin.rs index 03aa31fb5a..9d32919cfa 100644 --- a/src/header/common/access_control_allow_origin.rs +++ b/src/header/common/access_control_allow_origin.rs @@ -1,11 +1,11 @@ -use std::fmt; +use std::fmt::{self, Display}; use std::str; use url::Url; -use header; +use header::{Header, HeaderFormat}; /// The `Access-Control-Allow-Origin` response header, -/// part of [CORS](www.w3.org/TR/cors/#access-control-allow-origin-response-header) +/// part of [CORS](http://www.w3.org/TR/cors/#access-control-allow-origin-response-header) /// /// The `Access-Control-Allow-Origin` header indicates whether a resource /// can be shared based by returning the value of the Origin request header, @@ -15,45 +15,60 @@ use header; /// ```plain /// Access-Control-Allow-Origin = "Access-Control-Allow-Origin" ":" origin-list-or-null | "*" /// ``` -// FIXME: The documentation says differently (missing "null" value, "*" not used in practice, -// orgin list no list but single value) +/// +/// # Example values +/// * `null` +/// * `*` +/// * `http://google.com/` #[derive(Clone, PartialEq, Debug)] pub enum AccessControlAllowOrigin { /// Allow all origins Any, + /// A hidden origin + Null, /// Allow one particular origin Value(Url), } -impl header::Header for AccessControlAllowOrigin { +impl Header for AccessControlAllowOrigin { fn header_name() -> &'static str { "Access-Control-Allow-Origin" } fn parse_header(raw: &[Vec]) -> Option { if raw.len() == 1 { - match str::from_utf8(unsafe { &raw.get_unchecked(0)[..] }) { - Ok(s) => { - if s == "*" { - Some(AccessControlAllowOrigin::Any) - } else { - Url::parse(s).ok().map( - |url| AccessControlAllowOrigin::Value(url)) - } - }, - _ => return None, + match unsafe { &raw.get_unchecked(0)[..] } { + b"*" => Some(AccessControlAllowOrigin::Any), + b"null" => Some(AccessControlAllowOrigin::Null), + r => if let Ok(s) = str::from_utf8(r) { + Url::parse(s).ok().map(|url| AccessControlAllowOrigin::Value(url)) + } else { None } } - } else { - return None; - } + } else { None } } } -impl header::HeaderFormat for AccessControlAllowOrigin { +impl HeaderFormat for AccessControlAllowOrigin { fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { AccessControlAllowOrigin::Any => f.write_str("*"), - AccessControlAllowOrigin::Value(ref url) => fmt::Display::fmt(url, f) + AccessControlAllowOrigin::Null => f.write_str("null"), + AccessControlAllowOrigin::Value(ref url) => Display::fmt(url, f), } } } + +impl Display for AccessControlAllowOrigin { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + self.fmt_header(f) + } +} + +#[cfg(test)] +mod test_access_control_allow_orgin { + use header::*; + use super::AccessControlAllowOrigin as HeaderField; + test_header!(test1, vec![b"null"]); + test_header!(test2, vec![b"*"]); + test_header!(test3, vec![b"http://google.com/"]); +}