Merge pull request #502 from pyfisch/accesscontrolalloworigin
feat(headers): Allow `null` value in Access-Control-Allow-Origin
This commit is contained in:
		| @@ -1,11 +1,11 @@ | |||||||
| use std::fmt; | use std::fmt::{self, Display}; | ||||||
| use std::str; | use std::str; | ||||||
|  |  | ||||||
| use url::Url; | use url::Url; | ||||||
| use header; | use header::{Header, HeaderFormat}; | ||||||
|  |  | ||||||
| /// The `Access-Control-Allow-Origin` response header, | /// 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 | /// The `Access-Control-Allow-Origin` header indicates whether a resource | ||||||
| /// can be shared based by returning the value of the Origin request header, | /// can be shared based by returning the value of the Origin request header, | ||||||
| @@ -15,45 +15,60 @@ use header; | |||||||
| /// ```plain | /// ```plain | ||||||
| /// Access-Control-Allow-Origin = "Access-Control-Allow-Origin" ":" origin-list-or-null | "*" | /// 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)] | #[derive(Clone, PartialEq, Debug)] | ||||||
| pub enum AccessControlAllowOrigin { | pub enum AccessControlAllowOrigin { | ||||||
|     /// Allow all origins |     /// Allow all origins | ||||||
|     Any, |     Any, | ||||||
|  |     /// A hidden origin | ||||||
|  |     Null, | ||||||
|     /// Allow one particular origin |     /// Allow one particular origin | ||||||
|     Value(Url), |     Value(Url), | ||||||
| } | } | ||||||
|  |  | ||||||
| impl header::Header for AccessControlAllowOrigin { | impl Header for AccessControlAllowOrigin { | ||||||
|     fn header_name() -> &'static str { |     fn header_name() -> &'static str { | ||||||
|         "Access-Control-Allow-Origin" |         "Access-Control-Allow-Origin" | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn parse_header(raw: &[Vec<u8>]) -> Option<AccessControlAllowOrigin> { |     fn parse_header(raw: &[Vec<u8>]) -> Option<AccessControlAllowOrigin> { | ||||||
|         if raw.len() == 1 { |         if raw.len() == 1 { | ||||||
|             match str::from_utf8(unsafe { &raw.get_unchecked(0)[..] }) { |             match unsafe { &raw.get_unchecked(0)[..] } { | ||||||
|                 Ok(s) => { |                 b"*" => Some(AccessControlAllowOrigin::Any), | ||||||
|                     if s == "*" { |                 b"null" => Some(AccessControlAllowOrigin::Null), | ||||||
|                         Some(AccessControlAllowOrigin::Any) |                 r => if let Ok(s) = str::from_utf8(r) { | ||||||
|                     } else { |                     Url::parse(s).ok().map(|url| AccessControlAllowOrigin::Value(url)) | ||||||
|                         Url::parse(s).ok().map( |                 } else { None } | ||||||
|                             |url| AccessControlAllowOrigin::Value(url)) |  | ||||||
|             } |             } | ||||||
|                 }, |         } else { None } | ||||||
|                 _ => return None, |  | ||||||
|     } |     } | ||||||
|         } else { | } | ||||||
|             return None; |  | ||||||
|  | impl HeaderFormat for AccessControlAllowOrigin { | ||||||
|  |     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||||
|  |         match *self { | ||||||
|  |             AccessControlAllowOrigin::Any => f.write_str("*"), | ||||||
|  |             AccessControlAllowOrigin::Null => f.write_str("null"), | ||||||
|  |             AccessControlAllowOrigin::Value(ref url) => Display::fmt(url, f), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl header::HeaderFormat for AccessControlAllowOrigin { | impl Display for AccessControlAllowOrigin { | ||||||
|     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||||
|         match *self { |         self.fmt_header(f) | ||||||
|             AccessControlAllowOrigin::Any => f.write_str("*"), |  | ||||||
|             AccessControlAllowOrigin::Value(ref url) => fmt::Display::fmt(url, 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/"]); | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user