1 use header::{Header, Host, HeaderFormat};
2 use std::fmt;
3 use std::str::FromStr;
4 use header::parsing::from_one_raw_str;
5 
6 /// The `Origin` header.
7 ///
8 /// The `Origin` header is a version of the `Referer` header that is used for all HTTP fetches and `POST`s whose CORS flag is set.
9 /// This header is often used to inform recipients of the security context of where the request was initiated.
10 ///
11 ///
12 /// Following the spec, https://fetch.spec.whatwg.org/#origin-header, the value of this header is composed of
13 /// a String (scheme), header::Host (host/port)
14 ///
15 /// # Examples
16 /// ```
17 /// use hyper::header::{Headers, Origin};
18 ///
19 /// let mut headers = Headers::new();
20 /// headers.set(
21 ///     Origin::new("http", "hyper.rs", None)
22 /// );
23 /// ```
24 /// ```
25 /// use hyper::header::{Headers, Origin};
26 ///
27 /// let mut headers = Headers::new();
28 /// headers.set(
29 ///     Origin::new("https", "wikipedia.org", Some(443))
30 /// );
31 /// ```
32 
33 #[derive(Clone, Debug)]
34 pub struct Origin {
35     /// The scheme, such as http or https
36     pub scheme: String,
37     /// The host, such as Host{hostname: "hyper.rs".to_owned(), port: None}
38     pub host: Host,
39 }
40 
41 impl Origin {
42     /// Creates a new `Origin` header.
new<S: Into<String>, H: Into<String>>(scheme: S, hostname: H, port: Option<u16>) -> Origin43     pub fn new<S: Into<String>, H: Into<String>>(scheme: S, hostname: H, port: Option<u16>) -> Origin{
44         Origin {
45             scheme: scheme.into(),
46             host: Host {
47                 hostname: hostname.into(),
48                 port: port
49             }
50         }
51     }
52 }
53 
54 impl Header for Origin {
header_name() -> &'static str55     fn header_name() -> &'static str {
56         static NAME: &'static str = "Origin";
57         NAME
58     }
59 
parse_header(raw: &[Vec<u8>]) -> ::Result<Origin>60     fn parse_header(raw: &[Vec<u8>]) -> ::Result<Origin> {
61         from_one_raw_str(raw)
62     }
63 }
64 
65 impl FromStr for Origin {
66     type Err = ::Error;
67 
from_str(s: &str) -> ::Result<Origin>68     fn from_str(s: &str) -> ::Result<Origin> {
69         let idx = match s.find("://") {
70             Some(idx) => idx,
71             None => return Err(::Error::Header)
72         };
73         // idx + 3 because thats how long "://" is
74         let (scheme, etc) = (&s[..idx], &s[idx + 3..]);
75         let host = try!(Host::from_str(etc));
76 
77 
78         Ok(Origin{
79             scheme: scheme.to_owned(),
80             host: host
81         })
82     }
83 }
84 
85 impl HeaderFormat for Origin {
fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result86     fn fmt_header(&self, f: &mut fmt::Formatter) -> fmt::Result {
87         fmt::Display::fmt(self, f)
88     }
89 }
90 
91 impl fmt::Display for Origin {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result92     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93         write!(f, "{}://{}", self.scheme, self.host)
94     }
95 }
96 
97 impl PartialEq for Origin {
eq(&self, other: &Origin) -> bool98     fn eq(&self, other: &Origin) -> bool {
99         self.scheme == other.scheme && self.host == other.host
100     }
101 }
102 
103 
104 #[cfg(test)]
105 mod tests {
106     use super::Origin;
107     use header::Header;
108 
109     #[test]
test_origin()110     fn test_origin() {
111         let origin = Header::parse_header([b"http://foo.com".to_vec()].as_ref());
112         assert_eq!(origin.ok(), Some(Origin::new("http", "foo.com", None)));
113 
114         let origin = Header::parse_header([b"https://foo.com:443".to_vec()].as_ref());
115         assert_eq!(origin.ok(), Some(Origin::new("https", "foo.com", Some(443))));
116     }
117 }
118 
119 bench_header!(bench, Origin, { vec![b"https://foo.com".to_vec()] });
120