diff --git a/src/common/location.rs b/src/common/location.rs index 1af36d12..84538073 100644 --- a/src/common/location.rs +++ b/src/common/location.rs @@ -1,4 +1,6 @@ -use ::HeaderValue; +use crate::{Error, Header, HeaderName, HeaderValue}; +use http::{header, Uri}; +use std::iter; /// `Location` header, defined in /// [RFC7231](http://tools.ietf.org/html/rfc7231#section-7.1.2) @@ -20,21 +22,67 @@ use ::HeaderValue; /// /// # Examples /// -//TODO: make this a `Uri`? -#[derive(Clone, Debug, PartialEq, Header)] -pub struct Location(HeaderValue); +/// ``` +/// # extern crate headers_ext as headers; +/// # extern crate http; +/// use headers::Location; +/// use http::Uri; +/// let loc = Location::from(Uri::from_static("/auth/login")); +/// ``` + +#[derive(Clone, Debug, PartialEq)] +pub struct Location(Uri); + +impl Location { + /// Get the uri for this header + pub fn uri(&self) -> &Uri { + &self.0 + } +} + +impl Header for Location { + const NAME: &'static HeaderName = &header::LOCATION; + + fn decode<'i, I>(values: &mut I) -> Result + where + Self: Sized, + I: Iterator, + { + values + .next() + .and_then(|v| v.to_str().ok()?.parse().ok()) + .map(Location) + .ok_or_else(Error::invalid) + } + + fn encode>(&self, values: &mut E) { + values.extend(iter::once(self.into())) + } +} + +impl From for Location { + fn from(uri: Uri) -> Self { + Location(uri) + } +} + +impl From<&Location> for HeaderValue { + fn from(location: &Location) -> Self { + location.0.to_string().parse().unwrap() + } +} #[cfg(test)] mod tests { - use super::*; use super::super::test_decode; + use super::*; #[test] fn absolute_uri() { let s = "http://www.example.net/index.html"; let loc = test_decode::(&[s]).unwrap(); - assert_eq!(loc, Location(HeaderValue::from_static(s))); + assert_eq!(loc, Location(Uri::from_static(s))); } #[test] @@ -42,6 +90,6 @@ mod tests { let s = "/People.html#tim"; let loc = test_decode::(&[s]).unwrap(); - assert_eq!(loc, Location(HeaderValue::from_static(s))); + assert_eq!(loc, Location(Uri::from_static(s))); } }