change Host header to have hostname and port
This commit is contained in:
		| @@ -58,8 +58,12 @@ impl Request<Fresh> { | |||||||
|  |  | ||||||
|         let stream: S = try_io!(NetworkStream::connect(host.as_slice(), port, url.scheme.as_slice())); |         let stream: S = try_io!(NetworkStream::connect(host.as_slice(), port, url.scheme.as_slice())); | ||||||
|         let stream = ThroughWriter(BufferedWriter::new(stream.dynamic())); |         let stream = ThroughWriter(BufferedWriter::new(stream.dynamic())); | ||||||
|  |  | ||||||
|         let mut headers = Headers::new(); |         let mut headers = Headers::new(); | ||||||
|         headers.set(Host(format!("{}:{}", host, port))); |         headers.set(Host { | ||||||
|  |             hostname: host, | ||||||
|  |             port: Some(port), | ||||||
|  |         }); | ||||||
|  |  | ||||||
|         Ok(Request { |         Ok(Request { | ||||||
|             method: method, |             method: method, | ||||||
| @@ -188,32 +192,3 @@ impl Writer for Request<Streaming> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| #[cfg(test)] |  | ||||||
| mod tests { |  | ||||||
|     use header::common::Host; |  | ||||||
|     use method::Get; |  | ||||||
|     use net::MockStream; |  | ||||||
|     use url::Url; |  | ||||||
|     use super::Request; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     #[test] |  | ||||||
|     fn test_host_header() { |  | ||||||
|         fn check_host(url: &str, host_header: &str) { |  | ||||||
|             let request = Request::with_stream::<MockStream>( |  | ||||||
|                 Get, |  | ||||||
|                 Url::parse(url).unwrap(), |  | ||||||
|             ).unwrap(); |  | ||||||
|  |  | ||||||
|             assert_eq!( |  | ||||||
|                 &Host(host_header.to_string()), |  | ||||||
|                 request.headers().get::<Host>().unwrap() |  | ||||||
|             ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         check_host("http://www.example.com/path", "www.example.com:80"); |  | ||||||
|         check_host("https://www.example.com/path", "www.example.com:443"); |  | ||||||
|         check_host("http://www.example.com:8080/path", "www.example.com:8080"); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| use header::Header; | use header::Header; | ||||||
|  | use Port; | ||||||
| use std::fmt::{mod, Show}; | use std::fmt::{mod, Show}; | ||||||
| use super::util::from_one_raw_str; | use super::util::from_one_raw_str; | ||||||
|  |  | ||||||
| @@ -10,7 +11,12 @@ use super::util::from_one_raw_str; | |||||||
| /// Currently is just a String, but it should probably become a better type, | /// Currently is just a String, but it should probably become a better type, | ||||||
| /// like url::Host or something. | /// like url::Host or something. | ||||||
| #[deriving(Clone, PartialEq, Show)] | #[deriving(Clone, PartialEq, Show)] | ||||||
| pub struct Host(pub String); | pub struct Host { | ||||||
|  |     /// The hostname, such a example.domain. | ||||||
|  |     pub hostname: String, | ||||||
|  |     /// An optional port number. | ||||||
|  |     pub port: Option<Port> | ||||||
|  | } | ||||||
|  |  | ||||||
| impl Header for Host { | impl Header for Host { | ||||||
|     fn header_name(_: Option<Host>) -> &'static str { |     fn header_name(_: Option<Host>) -> &'static str { | ||||||
| @@ -18,12 +24,71 @@ impl Header for Host { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn parse_header(raw: &[Vec<u8>]) -> Option<Host> { |     fn parse_header(raw: &[Vec<u8>]) -> Option<Host> { | ||||||
|         from_one_raw_str(raw).map(|s| Host(s)) |         from_one_raw_str(raw).and_then(|mut s: String| { | ||||||
|  |             // FIXME: use rust-url to parse this | ||||||
|  |             // https://github.com/servo/rust-url/issues/42 | ||||||
|  |             let idx = { | ||||||
|  |                 let slice = s[]; | ||||||
|  |                 if slice.char_at(1) == '[' { | ||||||
|  |                     match slice.rfind(']') { | ||||||
|  |                         Some(idx) => { | ||||||
|  |                             if slice.len() > idx + 2 { | ||||||
|  |                                 Some(idx + 1) | ||||||
|  |                             } else { | ||||||
|  |                                 None | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                         None => return None // this is a bad ipv6 address... | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     slice.rfind(':') | ||||||
|  |                 } | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             let port = match idx { | ||||||
|  |                 Some(idx) => from_str::<u16>(s[].slice_from(idx + 1)), | ||||||
|  |                 None => None | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             match idx { | ||||||
|  |                 Some(idx) => s.truncate(idx), | ||||||
|  |                 None => () | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             Some(Host { | ||||||
|  |                 hostname: s, | ||||||
|  |                 port: port | ||||||
|  |             }) | ||||||
|  |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |     fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result { | ||||||
|         let Host(ref value) = *self; |         match self.port { | ||||||
|         value.fmt(fmt) |             None | Some(80) | Some(443) => self.hostname.fmt(fmt), | ||||||
|  |             Some(port) => write!(fmt, "{}:{}", self.hostname, port) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use super::Host; | ||||||
|  |     use header::Header; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_host() { | ||||||
|  |         let host = Header::parse_header([b"foo.com".to_vec()].as_slice()); | ||||||
|  |         assert_eq!(host, Some(Host { | ||||||
|  |             hostname: "foo.com".into_string(), | ||||||
|  |             port: None | ||||||
|  |         })); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         let host = Header::parse_header([b"foo.com:8080".to_vec()].as_slice()); | ||||||
|  |         assert_eq!(host, Some(Host { | ||||||
|  |             hostname: "foo.com".into_string(), | ||||||
|  |             port: Some(8080) | ||||||
|  |         })); | ||||||
|  |     } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -447,7 +447,7 @@ mod tests { | |||||||
|     fn test_headers_show() { |     fn test_headers_show() { | ||||||
|         let mut headers = Headers::new(); |         let mut headers = Headers::new(); | ||||||
|         headers.set(ContentLength(15)); |         headers.set(ContentLength(15)); | ||||||
|         headers.set(Host("foo.bar".into_string())); |         headers.set(Host { hostname: "foo.bar".into_string(), port: None }); | ||||||
|  |  | ||||||
|         let s = headers.to_string(); |         let s = headers.to_string(); | ||||||
|         // hashmap's iterators have arbitrary order, so we must sort first |         // hashmap's iterators have arbitrary order, so we must sort first | ||||||
|   | |||||||
| @@ -211,3 +211,4 @@ fn lift_ssl_error(ssl: SslError) -> IoError { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user