change Host header to have hostname and port
This commit is contained in:
@@ -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<Port>
|
||||
}
|
||||
|
||||
impl Header for Host {
|
||||
fn header_name(_: Option<Host>) -> &'static str {
|
||||
@@ -18,12 +24,71 @@ impl Header for 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 {
|
||||
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)
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user