Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/client/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use crate::{
ext::{RequestConfig, RequestConfigValue, RequestLevelOptions, RequestOrigHeaderMap},
},
header::{CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue, OrigHeaderMap},
into_url::IntoUrlSealed,
redirect,
};

Expand Down Expand Up @@ -823,7 +824,7 @@ where
headers,
..
} = parts;
let url = crate::into_url::IntoUrlSealed::into_url(uri.to_string())?;
let url = IntoUrlSealed::into_url(uri.to_string())?;
Ok(Request {
method,
url,
Expand All @@ -837,6 +838,7 @@ where
impl TryFrom<Request> for HttpRequest<Body> {
type Error = crate::Error;

#[inline]
fn try_from(req: Request) -> crate::Result<Self> {
req.try_into().map(|(_, http_req)| http_req)
}
Expand Down
28 changes: 24 additions & 4 deletions src/client/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::cookie;
use crate::{
Error, Upgraded,
core::{client::connect::HttpInfo, ext::ReasonPhrase},
response::ResponseUrl,
};

/// A Response to a submitted `Request`.
Expand Down Expand Up @@ -442,8 +443,6 @@ impl fmt::Debug for Response {
// to use `http::Response`, not `wreq::Response`.
impl<T: Into<Body>> From<http::Response<T>> for Response {
fn from(r: http::Response<T>) -> Response {
use crate::response::ResponseUrl;

let (mut parts, body) = r.into_parts();
let body: super::body::Body = body.into();
let url = parts
Expand All @@ -465,7 +464,9 @@ impl From<Response> for http::Response<Body> {
fn from(r: Response) -> http::Response<Body> {
let (parts, body) = r.res.into_parts();
let body = Body::wrap(body);
http::Response::from_parts(parts, body)
let mut response = http::Response::from_parts(parts, body);
response.extensions_mut().insert(ResponseUrl(*r.url));
response
}
}

Expand All @@ -482,7 +483,7 @@ mod tests {
use url::Url;

use super::Response;
use crate::ResponseBuilderExt;
use crate::{ResponseBuilderExt, response::ResponseExt};

#[test]
fn test_from_http_response() {
Expand All @@ -497,4 +498,23 @@ mod tests {
assert_eq!(response.status(), 200);
assert_eq!(*response.url(), url);
}

#[test]
fn test_from_http_response_with_url() {
let url = Url::parse("http://example.com").unwrap();
let response = Builder::new()
.status(200)
.url(url.clone())
.body("foo")
.unwrap();
let response = Response::from(response);

assert_eq!(response.status(), 200);
assert_eq!(*response.url(), url);

let http_response = http::Response::from(response);
let resp_url = http_response.url();
assert_eq!(http_response.status(), 200);
assert_eq!(resp_url, Some(&url));
}
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ pub use self::{
error::{Error, Result},
into_url::IntoUrl,
proxy::{NoProxy, Proxy},
response::ResponseBuilderExt,
response::{ResponseBuilderExt, ResponseExt},
};

fn _assert_impls() {
Expand Down
1 change: 1 addition & 0 deletions src/redirect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ impl<'a> Attempt<'a> {
pub fn previous(&self) -> &[Url] {
self.previous
}

/// Returns an action meaning wreq should follow the next URL.
pub fn follow(self) -> Action {
Action {
Expand Down
31 changes: 30 additions & 1 deletion src/response.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use url::Url;

use crate::Body;

#[derive(Debug, Clone, PartialEq)]
pub(crate) struct ResponseUrl(pub Url);

Expand All @@ -12,18 +14,33 @@ pub trait ResponseBuilderExt {
fn url(self, url: Url) -> Self;
}

/// Extension trait for http::Response objects
///
/// Provides methods to extract URL information from HTTP responses
pub trait ResponseExt {
/// Returns a reference to the `Url` associated with this response, if available.
fn url(&self) -> Option<&Url>;
}

impl ResponseBuilderExt for http::response::Builder {
fn url(self, url: Url) -> Self {
self.extension(ResponseUrl(url))
}
}

impl ResponseExt for http::Response<Body> {
fn url(&self) -> Option<&Url> {
self.extensions().get::<ResponseUrl>().map(|r| &r.0)
}
}

#[cfg(test)]
mod tests {
use http::response::Builder;
use url::Url;

use super::{ResponseBuilderExt, ResponseUrl};
use super::{ResponseBuilderExt, ResponseExt, ResponseUrl};
use crate::Body;

#[test]
fn test_response_builder_ext() {
Expand All @@ -39,4 +56,16 @@ mod tests {
Some(&ResponseUrl(url))
);
}

#[test]
fn test_response_ext() {
let url = Url::parse("http://example.com").unwrap();
let response = http::Response::builder()
.status(200)
.extension(ResponseUrl(url.clone()))
.body(Body::empty())
.unwrap();

assert_eq!(response.url(), Some(&url));
}
}
Loading