Skip to content

Commit b504712

Browse files
committed
changes from feedback, use Url type for url field
1 parent 96052dd commit b504712

File tree

1 file changed

+21
-14
lines changed

1 file changed

+21
-14
lines changed

src/content/content_location.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
use crate::headers::{HeaderName, HeaderValue, Headers, CONTENT_LOCATION};
22
use crate::{Status, Url};
33

4+
use std::convert::TryInto;
5+
6+
/// Indicates an alternate location for the returned data.
47
///
58
/// # Specifications
69
///
7-
/// - [RFC 7230, section 3.3.2: Content-Length](https://tools.ietf.org/html/rfc7231#section-3.1.4.2)
10+
/// - [RFC 7231, section 3.1.4.2: Content-Length](https://tools.ietf.org/html/rfc7231#section-3.1.4.2)
811
///
912
/// # Examples
1013
///
@@ -26,18 +29,21 @@ use crate::{Status, Url};
2629
/// ```
2730
#[derive(Debug)]
2831
pub struct ContentLocation {
29-
url: String,
32+
url: Url,
3033
}
3134

32-
#[allow(clippy::len_without_is_empty)]
3335
impl ContentLocation {
3436
/// Create a new instance of `Content-Location` header.
3537
pub fn new(url: String) -> Self {
36-
Self { url }
38+
Self { url : Url::parse(&url).unwrap() }
3739
}
3840

3941
/// Create a new instance from headers.
40-
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
42+
pub fn from_headers<U>(base_url: U, headers: impl AsRef<Headers>) -> crate::Result<Option<Self>>
43+
where
44+
U: TryInto<Url>,
45+
U::Error: std::fmt::Debug,
46+
{
4147
let headers = match headers.as_ref().get(CONTENT_LOCATION) {
4248
Some(headers) => headers,
4349
None => return Ok(None),
@@ -46,8 +52,9 @@ impl ContentLocation {
4652
// If we successfully parsed the header then there's always at least one
4753
// entry. We want the last entry.
4854
let value = headers.iter().last().unwrap();
49-
let url = Url::parse(value.as_str().trim()).status(400)?;
50-
Ok(Some(Self { url : url.into_string() }))
55+
let base = base_url.try_into().expect("Could not convert into a valid url");
56+
let url = base.join(value.as_str().trim()).status(400)?;
57+
Ok(Some(Self { url }))
5158
}
5259

5360
/// Sets the header.
@@ -62,7 +69,7 @@ impl ContentLocation {
6269

6370
/// Get the `HeaderValue`.
6471
pub fn value(&self) -> HeaderValue {
65-
let output = format!("{}", self.url);
72+
let output = format!("{}", self.url.as_str());
6673

6774
// SAFETY: the internal string is validated to be ASCII.
6875
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
@@ -75,7 +82,7 @@ impl ContentLocation {
7582

7683
/// Set the url.
7784
pub fn set_location(&mut self, location: &str) {
78-
self.url = location.to_string();
85+
self.url = Url::parse(location).unwrap();
7986
}
8087
}
8188

@@ -86,21 +93,21 @@ mod test {
8693

8794
#[test]
8895
fn smoke() -> crate::Result<()> {
89-
let content_location = ContentLocation::new("https://example.net/test".to_string());
96+
let content_location = ContentLocation::new("https://example.net/test.json".to_string());
9097

9198
let mut headers = Headers::new();
9299
content_location.apply(&mut headers);
93100

94-
let content_location = ContentLocation::from_headers(headers)?.unwrap();
95-
assert_eq!(content_location.location(), "https://example.net/test");
101+
let content_location = ContentLocation::from_headers( Url::parse("https://example.net/").unwrap(), headers )?.unwrap();
102+
assert_eq!(content_location.location(), "https://example.net/test.json");
96103
Ok(())
97104
}
98105

99106
#[test]
100107
fn bad_request_on_parse_error() -> crate::Result<()> {
101108
let mut headers = Headers::new();
102-
headers.insert(CONTENT_LOCATION, "<nori ate the tag. yum.>");
103-
let err = ContentLocation::from_headers(headers).unwrap_err();
109+
headers.insert(CONTENT_LOCATION, "htt://<nori ate the tag. yum.>");
110+
let err = ContentLocation::from_headers(Url::parse("https://example.net").unwrap(), headers).unwrap_err();
104111
assert_eq!(err.status(), 400);
105112
Ok(())
106113
}

0 commit comments

Comments
 (0)