diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 98cf54ac3..bb0844e05 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -4,7 +4,7 @@ ### Added -- Add `HttpRequest::full_uri()` method to get the full uri of an incoming request. +- Add `HttpRequest::full_url()` method to get the complete URL of the request. ### Fixed diff --git a/actix-web/src/request.rs b/actix-web/src/request.rs index 22841746d..47b3e3d88 100644 --- a/actix-web/src/request.rs +++ b/actix-web/src/request.rs @@ -91,16 +91,33 @@ impl HttpRequest { &self.head().uri } - /// Request's full uri (scheme + host + origin). - #[inline] - pub fn full_uri(&self) -> Uri { - let uri: Uri = Uri::builder() - .scheme(self.connection_info().scheme()) - .authority(self.connection_info().host()) - .path_and_query(self.uri().to_string()) - .build() - .unwrap(); - uri + /// Returns request's original full URL. + /// + /// Reconstructed URL is best-effort, using [`connection_info`](HttpRequest::connection_info()) + /// to get forwarded scheme & host. + /// + /// ``` + /// use actix_web::test::TestRequest; + /// let req = TestRequest::with_uri("http://10.1.2.3:8443/api?id=4&name=foo") + /// .insert_header(("host", "example.com")) + /// .to_http_request(); + /// + /// assert_eq!( + /// req.full_url().as_str(), + /// "http://example.com/api?id=4&name=foo", + /// ); + /// ``` + pub fn full_url(&self) -> url::Url { + let info = self.connection_info(); + let scheme = info.scheme(); + let host = info.host(); + let path_and_query = self + .uri() + .path_and_query() + .map(|paq| paq.as_str()) + .unwrap_or("/"); + + url::Url::parse(&format!("{scheme}://{host}{path_and_query}")).unwrap() } /// Read the Request method. @@ -977,9 +994,25 @@ mod tests { } #[test] - fn check_full_uri() { + fn check_full_url() { let req = TestRequest::with_uri("/api?id=4&name=foo").to_http_request(); + assert_eq!( + req.full_url().as_str(), + "http://localhost:8080/api?id=4&name=foo", + ); - assert_eq!(req.full_uri(), "http://localhost:8080/api?id=4&name=foo"); + let req = TestRequest::with_uri("https://example.com/api?id=4&name=foo").to_http_request(); + assert_eq!( + req.full_url().as_str(), + "https://example.com/api?id=4&name=foo", + ); + + let req = TestRequest::with_uri("http://10.1.2.3:8443/api?id=4&name=foo") + .insert_header(("host", "example.com")) + .to_http_request(); + assert_eq!( + req.full_url().as_str(), + "http://example.com/api?id=4&name=foo", + ); } }