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