mirror of
https://github.com/tokio-rs/axum.git
synced 2025-01-01 00:50:32 +01:00
Make Path
extractor work with Deserialize
impls using &str
(#990)
* `Path` extractor works with `Deserialize` impls using `&str` Before this change the extractor `Path<Test>` would fail if the `Deserialize` implementation of `Test` was calling `Deserializer::deserialize_str()`. Now we use `Visitor::visit_borrowed_str()` instead of `Visitor::visit_str()` which is also recommended in the guide to implement a deserializer [1]. [1]: https://serde.rs/impl-deserializer.html * fixup! `Path` extractor works with `Deserialize` impls using `&str` * add test for percent decoding Co-authored-by: David Pedersen <david.pdrsn@gmail.com>
This commit is contained in:
parent
d1043db254
commit
8cc052f38b
2 changed files with 28 additions and 1 deletions
|
@ -88,7 +88,7 @@ impl<'de> Deserializer<'de> for PathDeserializer<'de> {
|
|||
.got(self.url_params.len())
|
||||
.expected(1));
|
||||
}
|
||||
visitor.visit_str(&self.url_params[0].1)
|
||||
visitor.visit_borrowed_str(&self.url_params[0].1)
|
||||
}
|
||||
|
||||
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
|
@ -608,6 +608,8 @@ mod tests {
|
|||
check_single_value!(f64, "123", 123.0);
|
||||
check_single_value!(String, "abc", "abc");
|
||||
check_single_value!(String, "one%20two", "one two");
|
||||
check_single_value!(&str, "abc", "abc");
|
||||
check_single_value!(&str, "one%20two", "one two");
|
||||
check_single_value!(char, "a", 'a');
|
||||
|
||||
let url_params = create_url_params(vec![("a", "B")]);
|
||||
|
|
|
@ -514,4 +514,29 @@ mod tests {
|
|||
"No paths parameters found for matched route. Are you also extracting `Request<_>`?"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn str_reference_deserialize() {
|
||||
struct Param(String);
|
||||
impl<'de> serde::Deserialize<'de> for Param {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let s = <&str as serde::Deserialize>::deserialize(deserializer)?;
|
||||
Ok(Param(s.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
let app = Router::new().route("/:key", get(|param: Path<Param>| async move { param.0 .0 }));
|
||||
|
||||
let client = TestClient::new(app);
|
||||
|
||||
let res = client.get("/foo").send().await;
|
||||
assert_eq!(res.text().await, "foo");
|
||||
|
||||
// percent decoding should also work
|
||||
let res = client.get("/foo%20bar").send().await;
|
||||
assert_eq!(res.text().await, "foo bar");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue