Skip to content

Commit a1e59fc

Browse files
committed
Merge pull request #502 from pyfisch/accesscontrolalloworigin
feat(headers): Allow `null` value in Access-Control-Allow-Origin
2 parents c238890 + 5e34171 commit a1e59fc

File tree

1 file changed

+36
-21
lines changed

1 file changed

+36
-21
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use std::fmt;
1+
use std::fmt::{self, Display};
22
use std::str;
33

44
use url::Url;
5-
use header;
5+
use header::{Header, HeaderFormat};
66

77
/// The `Access-Control-Allow-Origin` response header,
8-
/// part of [CORS](www.w3.org/TR/cors/#access-control-allow-origin-response-header)
8+
/// part of [CORS](http://www.w3.org/TR/cors/#access-control-allow-origin-response-header)
99
///
1010
/// The `Access-Control-Allow-Origin` header indicates whether a resource
1111
/// can be shared based by returning the value of the Origin request header,
@@ -15,45 +15,60 @@ use header;
1515
/// ```plain
1616
/// Access-Control-Allow-Origin = "Access-Control-Allow-Origin" ":" origin-list-or-null | "*"
1717
/// ```
18-
// FIXME: The documentation says differently (missing "null" value, "*" not used in practice,
19-
// orgin list no list but single value)
18+
///
19+
/// # Example values
20+
/// * `null`
21+
/// * `*`
22+
/// * `http://google.com/`
2023
#[derive(Clone, PartialEq, Debug)]
2124
pub enum AccessControlAllowOrigin {
2225
/// Allow all origins
2326
Any,
27+
/// A hidden origin
28+
Null,
2429
/// Allow one particular origin
2530
Value(Url),
2631
}
2732

28-
impl header::Header for AccessControlAllowOrigin {
33+
impl Header for AccessControlAllowOrigin {
2934
fn header_name() -> &'static str {
3035
"Access-Control-Allow-Origin"
3136
}
3237

3338
fn parse_header(raw: &[Vec<u8>]) -> Option<AccessControlAllowOrigin> {
3439
if raw.len() == 1 {
35-
match str::from_utf8(unsafe { &raw.get_unchecked(0)[..] }) {
36-
Ok(s) => {
37-
if s == "*" {
38-
Some(AccessControlAllowOrigin::Any)
39-
} else {
40-
Url::parse(s).ok().map(
41-
|url| AccessControlAllowOrigin::Value(url))
42-
}
43-
},
44-
_ => return None,
40+
match unsafe { &raw.get_unchecked(0)[..] } {
41+
b"*" => Some(AccessControlAllowOrigin::Any),
42+
b"null" => Some(AccessControlAllowOrigin::Null),
43+
r => if let Ok(s) = str::from_utf8(r) {
44+
Url::parse(s).ok().map(|url| AccessControlAllowOrigin::Value(url))
45+
} else { None }
4546
}
46-
} else {
47-
return None;
48-
}
47+
} else { None }
4948
}
5049
}
5150

52-
impl header::HeaderFormat for AccessControlAllowOrigin {
51+
impl HeaderFormat for AccessControlAllowOrigin {
5352
fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
5453
match *self {
5554
AccessControlAllowOrigin::Any => f.write_str("*"),
56-
AccessControlAllowOrigin::Value(ref url) => fmt::Display::fmt(url, f)
55+
AccessControlAllowOrigin::Null => f.write_str("null"),
56+
AccessControlAllowOrigin::Value(ref url) => Display::fmt(url, f),
5757
}
5858
}
5959
}
60+
61+
impl Display for AccessControlAllowOrigin {
62+
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
63+
self.fmt_header(f)
64+
}
65+
}
66+
67+
#[cfg(test)]
68+
mod test_access_control_allow_orgin {
69+
use header::*;
70+
use super::AccessControlAllowOrigin as HeaderField;
71+
test_header!(test1, vec![b"null"]);
72+
test_header!(test2, vec![b"*"]);
73+
test_header!(test3, vec![b"http://google.com/"]);
74+
}

0 commit comments

Comments
 (0)