From f8d5ad6b5349843d16ec391c711b7b05eddce428 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Tue, 21 Jul 2020 01:54:26 +0200 Subject: [PATCH] Make web::Path a tuple struct with a public inner value (#1594) Co-authored-by: Rob Ede --- CHANGES.md | 3 +++ MIGRATION.md | 20 +++++++++++++++++ README.md | 4 ++-- src/lib.rs | 4 ++-- src/types/path.rs | 57 +++++++++++++++++++++++------------------------ 5 files changed, 55 insertions(+), 33 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4b6697a7f..5783da75a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,10 +4,13 @@ ### Changed * `PayloadConfig` is now also considered in `Bytes` and `String` extractors when set using `App::data`. [#1610] +* `web::Path` now has a public representation: `web::Path(pub T)` that enables + destructuring. [#1594] ### Fixed * Memory leak of app data in pooled requests. [#1609] +[#1594]: https://github.com/actix/actix-web/pull/1594 [#1609]: https://github.com/actix/actix-web/pull/1609 [#1610]: https://github.com/actix/actix-web/pull/1610 diff --git a/MIGRATION.md b/MIGRATION.md index d2e9735fb..7459b5b2d 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -12,6 +12,26 @@ * `BodySize::Sized64` variant has been removed. `BodySize::Sized` now receives a `u64` instead of a `usize`. +* Code that was using `path.` to access a `web::Path<(A, B, C)>`s elements now needs to use + destructuring or `.into_inner()`. For example: + + ```rust + // Previously: + async fn some_route(path: web::Path<(String, String)>) -> String { + format!("Hello, {} {}", path.0, path.1) + } + + // Now (this also worked before): + async fn some_route(path: web::Path<(String, String)>) -> String { + let (first_name, last_name) = path.into_inner(); + format!("Hello, {} {}", first_name, last_name) + } + // Or (this wasn't previously supported): + async fn some_route(web::Path((first_name, last_name)): web::Path<(String, String)>) -> String { + format!("Hello, {} {}", first_name, last_name) + } + ``` + ## 2.0.0 * `HttpServer::start()` renamed to `HttpServer::run()`. It also possible to diff --git a/README.md b/README.md index 4d6bac29c..4f6a16199 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,8 @@ Code: use actix_web::{get, web, App, HttpServer, Responder}; #[get("/{id}/{name}/index.html")] -async fn index(info: web::Path<(u32, String)>) -> impl Responder { - format!("Hello {}! id:{}", info.1, info.0) +async fn index(web::Path((id, name)): web::Path<(u32, String)>) -> impl Responder { + format!("Hello {}! id:{}", name, id) } #[actix_web::main] diff --git a/src/lib.rs b/src/lib.rs index eb46af664..8776a62b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,8 +9,8 @@ //! use actix_web::{get, web, App, HttpServer, Responder}; //! //! #[get("/{id}/{name}/index.html")] -//! async fn index(info: web::Path<(u32, String)>) -> impl Responder { -//! format!("Hello {}! id:{}", info.1, info.0) +//! async fn index(web::Path((id, name)): web::Path<(u32, String)>) -> impl Responder { +//! format!("Hello {}! id:{}", name, id) //! } //! //! #[actix_web::main] diff --git a/src/types/path.rs b/src/types/path.rs index 82050171c..dbb5f3ee0 100644 --- a/src/types/path.rs +++ b/src/types/path.rs @@ -25,8 +25,8 @@ use crate::FromRequest; /// /// extract path info from "/{username}/{count}/index.html" url /// /// {username} - deserializes to a String /// /// {count} - - deserializes to a u32 -/// async fn index(info: web::Path<(String, u32)>) -> String { -/// format!("Welcome {}! {}", info.0, info.1) +/// async fn index(web::Path((username, count)): web::Path<(String, u32)>) -> String { +/// format!("Welcome {}! {}", username, count) /// } /// /// fn main() { @@ -61,20 +61,18 @@ use crate::FromRequest; /// ); /// } /// ``` -pub struct Path { - inner: T, -} +pub struct Path(pub T); impl Path { /// Deconstruct to an inner value pub fn into_inner(self) -> T { - self.inner + self.0 } } impl AsRef for Path { fn as_ref(&self) -> &T { - &self.inner + &self.0 } } @@ -82,31 +80,31 @@ impl ops::Deref for Path { type Target = T; fn deref(&self) -> &T { - &self.inner + &self.0 } } impl ops::DerefMut for Path { fn deref_mut(&mut self) -> &mut T { - &mut self.inner + &mut self.0 } } impl From for Path { fn from(inner: T) -> Path { - Path { inner } + Path(inner) } } impl fmt::Debug for Path { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.inner.fmt(f) + self.0.fmt(f) } } impl fmt::Display for Path { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.inner.fmt(f) + self.0.fmt(f) } } @@ -120,8 +118,8 @@ impl fmt::Display for Path { /// /// extract path info from "/{username}/{count}/index.html" url /// /// {username} - deserializes to a String /// /// {count} - - deserializes to a u32 -/// async fn index(info: web::Path<(String, u32)>) -> String { -/// format!("Welcome {}! {}", info.0, info.1) +/// async fn index(web::Path((username, count)): web::Path<(String, u32)>) -> String { +/// format!("Welcome {}! {}", username, count) /// } /// /// fn main() { @@ -173,7 +171,7 @@ where ready( de::Deserialize::deserialize(PathDeserializer::new(req.match_info())) - .map(|inner| Path { inner }) + .map(Path) .map_err(move |e| { log::debug!( "Failed during Path extractor deserialization. \ @@ -290,21 +288,22 @@ mod tests { resource.match_path(req.match_info_mut()); let (req, mut pl) = req.into_parts(); - let res = <(Path<(String, String)>,)>::from_request(&req, &mut pl) + let (Path(res),) = <(Path<(String, String)>,)>::from_request(&req, &mut pl) .await .unwrap(); - assert_eq!((res.0).0, "name"); - assert_eq!((res.0).1, "user1"); + assert_eq!(res.0, "name"); + assert_eq!(res.1, "user1"); - let res = <(Path<(String, String)>, Path<(String, String)>)>::from_request( - &req, &mut pl, - ) - .await - .unwrap(); - assert_eq!((res.0).0, "name"); - assert_eq!((res.0).1, "user1"); - assert_eq!((res.1).0, "name"); - assert_eq!((res.1).1, "user1"); + let (Path(a), Path(b)) = + <(Path<(String, String)>, Path<(String, String)>)>::from_request( + &req, &mut pl, + ) + .await + .unwrap(); + assert_eq!(a.0, "name"); + assert_eq!(a.1, "user1"); + assert_eq!(b.0, "name"); + assert_eq!(b.1, "user1"); let () = <()>::from_request(&req, &mut pl).await.unwrap(); } @@ -329,7 +328,7 @@ mod tests { let s = s.into_inner(); assert_eq!(s.value, "user2"); - let s = Path::<(String, String)>::from_request(&req, &mut pl) + let Path(s) = Path::<(String, String)>::from_request(&req, &mut pl) .await .unwrap(); assert_eq!(s.0, "name"); @@ -344,7 +343,7 @@ mod tests { assert_eq!(s.as_ref().key, "name"); assert_eq!(s.value, 32); - let s = Path::<(String, u8)>::from_request(&req, &mut pl) + let Path(s) = Path::<(String, u8)>::from_request(&req, &mut pl) .await .unwrap(); assert_eq!(s.0, "name");