diff --git a/src/client/request.rs b/src/client/request.rs index 38aeaf7c..fc1e6844 100644 --- a/src/client/request.rs +++ b/src/client/request.rs @@ -58,8 +58,12 @@ impl Request { let stream: S = try_io!(NetworkStream::connect(host.as_slice(), port, url.scheme.as_slice())); let stream = ThroughWriter(BufferedWriter::new(stream.dynamic())); + let mut headers = Headers::new(); - headers.set(Host(format!("{}:{}", host, port))); + headers.set(Host { + hostname: host, + port: Some(port), + }); Ok(Request { method: method, @@ -188,32 +192,3 @@ impl Writer for Request { } } - -#[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::( - Get, - Url::parse(url).unwrap(), - ).unwrap(); - - assert_eq!( - &Host(host_header.to_string()), - request.headers().get::().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"); - } -} diff --git a/src/header/common/host.rs b/src/header/common/host.rs index 64a0d4e2..d1d13888 100644 --- a/src/header/common/host.rs +++ b/src/header/common/host.rs @@ -1,4 +1,5 @@ use header::Header; +use Port; use std::fmt::{mod, Show}; 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, /// like url::Host or something. #[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 +} impl Header for Host { fn header_name(_: Option) -> &'static str { @@ -18,12 +24,71 @@ impl Header for Host { } fn parse_header(raw: &[Vec]) -> Option { - 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::(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 { - let Host(ref value) = *self; - value.fmt(fmt) + match self.port { + 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) + })); + } +} diff --git a/src/header/mod.rs b/src/header/mod.rs index 938c41d7..5c56b123 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -447,7 +447,7 @@ mod tests { fn test_headers_show() { let mut headers = Headers::new(); 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(); // hashmap's iterators have arbitrary order, so we must sort first diff --git a/src/net.rs b/src/net.rs index 6473e586..9465bd53 100644 --- a/src/net.rs +++ b/src/net.rs @@ -211,3 +211,4 @@ fn lift_ssl_error(ssl: SslError) -> IoError { } } } +