From b36d53b5877e365ad21cb95c43a70c8c54742e90 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 23 Apr 2022 02:53:12 +0100 Subject: [PATCH] support multi-value items in Query --- actix-web-lab/CHANGELOG.md | 1 + actix-web-lab/Cargo.toml | 2 +- actix-web-lab/README.md | 2 +- actix-web-lab/src/query.rs | 19 +++++++++++++++++-- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/actix-web-lab/CHANGELOG.md b/actix-web-lab/CHANGELOG.md index a0d68ddf..adee4947 100644 --- a/actix-web-lab/CHANGELOG.md +++ b/actix-web-lab/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## Unreleased - 2022-xx-xx +- `Query` extractor now supports collecting multi-value items into a `Vec`. ## 0.16.0 - 2022-04-11 diff --git a/actix-web-lab/Cargo.toml b/actix-web-lab/Cargo.toml index 07663a22..7d2dbca3 100644 --- a/actix-web-lab/Cargo.toml +++ b/actix-web-lab/Cargo.toml @@ -48,7 +48,7 @@ once_cell = "1.8" pin-project-lite = "0.2.7" serde = "1" serde_json = "1" -serde_urlencoded = "0.7" +serde_html_form = "0.1" subtle = "2.4" tokio = { version = "1.13.1", features = ["sync", "macros"] } tracing = { version = "0.1.30", features = ["log"] } diff --git a/actix-web-lab/README.md b/actix-web-lab/README.md index f1284cb9..307eaba7 100644 --- a/actix-web-lab/README.md +++ b/actix-web-lab/README.md @@ -35,7 +35,7 @@ - `LocalData`: app data/state that uses an `Rc` internally, avoiding atomic overhead (alternative to `Data>`) [(docs)](https://docs.rs/actix-web-lab/0.16.0/actix_web_lab/extract/struct.DataSwap.html) - `Json`: simplified JSON extractor with const-generic limits [(docs)](https://docs.rs/actix-web-lab/0.16.0/actix_web_lab/extract/struct.Json.html) - `Path`: simplified path parameter extractor that supports destructuring [(docs)](https://docs.rs/actix-web-lab/0.16.0/actix_web_lab/extract/struct.Path.html) -- `Query`: simplified query-string extractor [(docs)](https://docs.rs/actix-web-lab/0.16.0/actix_web_lab/extract/struct.Query.html) +- `Query`: simplified query-string extractor that can also collect multi-value items [(docs)](https://docs.rs/actix-web-lab/0.16.0/actix_web_lab/extract/struct.Query.html) - `RequestSignature`: wraps an extractor and calculates a request signature alongside [(docs)](https://docs.rs/actix-web-lab/0.16.0/actix_web_lab/extract/struct.RequestSignature.html) ### Macros diff --git a/actix-web-lab/src/query.rs b/actix-web-lab/src/query.rs index 550cf1f2..0742e60b 100644 --- a/actix-web-lab/src/query.rs +++ b/actix-web-lab/src/query.rs @@ -85,7 +85,7 @@ impl Query { /// assert!(numbers.get("three").is_none()); /// ``` pub fn from_query(query_str: &str) -> Result { - serde_urlencoded::from_str::(query_str) + serde_html_form::from_str::(query_str) .map(Self) .map_err(QueryPayloadError::Deserialize) } @@ -118,7 +118,7 @@ impl FromRequest for Query { #[inline] fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { - serde_urlencoded::from_str::(req.query_string()) + serde_html_form::from_str::(req.query_string()) .map(|val| ready(Ok(Query(val)))) .unwrap_or_else(move |e| { let err = QueryPayloadError::Deserialize(e); @@ -166,6 +166,21 @@ mod tests { assert_eq!(s.id, "test1"); } + #[actix_web::test] + async fn extract_array() { + #[derive(Debug, Deserialize)] + struct Test { + #[serde(rename = "user")] + users: Vec, + } + + let req = TestRequest::with_uri("/?user=foo&user=bar").to_srv_request(); + let s = Query::::from_query(req.query_string()).unwrap(); + + assert_eq!(s.users[0], "foo"); + assert_eq!(s.users[1], "bar"); + } + #[actix_web::test] async fn test_request_extract() { let req = TestRequest::with_uri("/name/user1/").to_srv_request();