Skip to content

Commit 72b24c7

Browse files
authored
feat(response): preserve URL when converting Response to http::Response (#897)
1 parent 70dd6d9 commit 72b24c7

5 files changed

Lines changed: 59 additions & 7 deletions

File tree

src/client/request.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use crate::{
3131
ext::{RequestConfig, RequestConfigValue, RequestLevelOptions, RequestOrigHeaderMap},
3232
},
3333
header::{CONTENT_TYPE, HeaderMap, HeaderName, HeaderValue, OrigHeaderMap},
34+
into_url::IntoUrlSealed,
3435
redirect,
3536
};
3637

@@ -823,7 +824,7 @@ where
823824
headers,
824825
..
825826
} = parts;
826-
let url = crate::into_url::IntoUrlSealed::into_url(uri.to_string())?;
827+
let url = IntoUrlSealed::into_url(uri.to_string())?;
827828
Ok(Request {
828829
method,
829830
url,
@@ -837,6 +838,7 @@ where
837838
impl TryFrom<Request> for HttpRequest<Body> {
838839
type Error = crate::Error;
839840

841+
#[inline]
840842
fn try_from(req: Request) -> crate::Result<Self> {
841843
req.try_into().map(|(_, http_req)| http_req)
842844
}

src/client/response.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::cookie;
1616
use crate::{
1717
Error, Upgraded,
1818
core::{client::connect::HttpInfo, ext::ReasonPhrase},
19+
response::ResponseUrl,
1920
};
2021

2122
/// A Response to a submitted `Request`.
@@ -442,8 +443,6 @@ impl fmt::Debug for Response {
442443
// to use `http::Response`, not `wreq::Response`.
443444
impl<T: Into<Body>> From<http::Response<T>> for Response {
444445
fn from(r: http::Response<T>) -> Response {
445-
use crate::response::ResponseUrl;
446-
447446
let (mut parts, body) = r.into_parts();
448447
let body: super::body::Body = body.into();
449448
let url = parts
@@ -465,7 +464,9 @@ impl From<Response> for http::Response<Body> {
465464
fn from(r: Response) -> http::Response<Body> {
466465
let (parts, body) = r.res.into_parts();
467466
let body = Body::wrap(body);
468-
http::Response::from_parts(parts, body)
467+
let mut response = http::Response::from_parts(parts, body);
468+
response.extensions_mut().insert(ResponseUrl(*r.url));
469+
response
469470
}
470471
}
471472

@@ -482,7 +483,7 @@ mod tests {
482483
use url::Url;
483484

484485
use super::Response;
485-
use crate::ResponseBuilderExt;
486+
use crate::{ResponseBuilderExt, response::ResponseExt};
486487

487488
#[test]
488489
fn test_from_http_response() {
@@ -497,4 +498,23 @@ mod tests {
497498
assert_eq!(response.status(), 200);
498499
assert_eq!(*response.url(), url);
499500
}
501+
502+
#[test]
503+
fn test_from_http_response_with_url() {
504+
let url = Url::parse("http://example.com").unwrap();
505+
let response = Builder::new()
506+
.status(200)
507+
.url(url.clone())
508+
.body("foo")
509+
.unwrap();
510+
let response = Response::from(response);
511+
512+
assert_eq!(response.status(), 200);
513+
assert_eq!(*response.url(), url);
514+
515+
let http_response = http::Response::from(response);
516+
let resp_url = http_response.url();
517+
assert_eq!(http_response.status(), 200);
518+
assert_eq!(resp_url, Some(&url));
519+
}
500520
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ pub use self::{
311311
error::{Error, Result},
312312
into_url::IntoUrl,
313313
proxy::{NoProxy, Proxy},
314-
response::ResponseBuilderExt,
314+
response::{ResponseBuilderExt, ResponseExt},
315315
};
316316

317317
fn _assert_impls() {

src/redirect.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ impl<'a> Attempt<'a> {
179179
pub fn previous(&self) -> &[Url] {
180180
self.previous
181181
}
182+
182183
/// Returns an action meaning wreq should follow the next URL.
183184
pub fn follow(self) -> Action {
184185
Action {

src/response.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use url::Url;
22

3+
use crate::Body;
4+
35
#[derive(Debug, Clone, PartialEq)]
46
pub(crate) struct ResponseUrl(pub Url);
57

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

17+
/// Extension trait for http::Response objects
18+
///
19+
/// Provides methods to extract URL information from HTTP responses
20+
pub trait ResponseExt {
21+
/// Returns a reference to the `Url` associated with this response, if available.
22+
fn url(&self) -> Option<&Url>;
23+
}
24+
1525
impl ResponseBuilderExt for http::response::Builder {
1626
fn url(self, url: Url) -> Self {
1727
self.extension(ResponseUrl(url))
1828
}
1929
}
2030

31+
impl ResponseExt for http::Response<Body> {
32+
fn url(&self) -> Option<&Url> {
33+
self.extensions().get::<ResponseUrl>().map(|r| &r.0)
34+
}
35+
}
36+
2137
#[cfg(test)]
2238
mod tests {
2339
use http::response::Builder;
2440
use url::Url;
2541

26-
use super::{ResponseBuilderExt, ResponseUrl};
42+
use super::{ResponseBuilderExt, ResponseExt, ResponseUrl};
43+
use crate::Body;
2744

2845
#[test]
2946
fn test_response_builder_ext() {
@@ -39,4 +56,16 @@ mod tests {
3956
Some(&ResponseUrl(url))
4057
);
4158
}
59+
60+
#[test]
61+
fn test_response_ext() {
62+
let url = Url::parse("http://example.com").unwrap();
63+
let response = http::Response::builder()
64+
.status(200)
65+
.extension(ResponseUrl(url.clone()))
66+
.body(Body::empty())
67+
.unwrap();
68+
69+
assert_eq!(response.url(), Some(&url));
70+
}
4271
}

0 commit comments

Comments
 (0)