ureq/response.rs
1use http::Uri;
2
3use crate::body::Body;
4use crate::http;
5
6#[derive(Debug, Clone)]
7pub(crate) struct ResponseUri(pub http::Uri);
8
9#[derive(Debug, Clone)]
10pub(crate) struct RedirectHistory(pub Vec<Uri>);
11
12/// Extension trait for [`http::Response<Body>`].
13///
14/// Adds additional convenience methods to the `Response` that are not available
15/// in the plain http API.
16pub trait ResponseExt {
17 /// The Uri that ultimately this Response is about.
18 ///
19 /// This can differ from the request uri when we have followed redirects.
20 ///
21 /// ```
22 /// use ureq::ResponseExt;
23 ///
24 /// let res = ureq::get("https://httpbin.org/redirect-to?url=%2Fget")
25 /// .call().unwrap();
26 ///
27 /// assert_eq!(res.get_uri(), "https://httpbin.org/get");
28 /// ```
29 fn get_uri(&self) -> &Uri;
30
31 /// The full history of uris, including the request and final uri.
32 ///
33 /// Returns `None` when [`Config::save_redirect_history`][crate::config::Config::save_redirect_history]
34 /// is `false`.
35 ///
36 ///
37 /// ```
38 /// # use ureq::http::Uri;
39 /// use ureq::ResponseExt;
40 ///
41 /// let uri1: Uri = "https://httpbin.org/redirect-to?url=%2Fget".parse().unwrap();
42 /// let uri2: Uri = "https://httpbin.org/get".parse::<Uri>().unwrap();
43 ///
44 /// let res = ureq::get(&uri1)
45 /// .config()
46 /// .save_redirect_history(true)
47 /// .build()
48 /// .call().unwrap();
49 ///
50 /// let history = res.get_redirect_history().unwrap();
51 ///
52 /// assert_eq!(history, &[uri1, uri2]);
53 /// ```
54 fn get_redirect_history(&self) -> Option<&[Uri]>;
55}
56
57impl ResponseExt for http::Response<Body> {
58 fn get_uri(&self) -> &Uri {
59 &self
60 .extensions()
61 .get::<ResponseUri>()
62 .expect("uri to have been set")
63 .0
64 }
65
66 fn get_redirect_history(&self) -> Option<&[Uri]> {
67 self.extensions()
68 .get::<RedirectHistory>()
69 .map(|r| r.0.as_ref())
70 }
71}