mirror of
https://github.com/tokio-rs/axum.git
synced 2024-12-28 07:20:12 +01:00
Stricter path deserialization for tuples and tuple structs (#2931)
This commit is contained in:
parent
068c9a3e96
commit
4179d11797
3 changed files with 47 additions and 16 deletions
|
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
# Unreleased
|
||||||
|
|
||||||
|
- **breaking:** The tuple and tuple_struct `Path` extractor deserializers now check that the number of parameters matches the tuple length exactly ([#2931])
|
||||||
|
|
||||||
|
[#2931]: https://github.com/tokio-rs/axum/pull/2931
|
||||||
|
|
||||||
# 0.7.6
|
# 0.7.6
|
||||||
|
|
||||||
- **change:** Avoid cloning `Arc` during deserialization of `Path`
|
- **change:** Avoid cloning `Arc` during deserialization of `Path`
|
||||||
|
|
|
@ -140,7 +140,7 @@ impl<'de> Deserializer<'de> for PathDeserializer<'de> {
|
||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
if self.url_params.len() < len {
|
if self.url_params.len() != len {
|
||||||
return Err(PathDeserializationError::wrong_number_of_parameters()
|
return Err(PathDeserializationError::wrong_number_of_parameters()
|
||||||
.got(self.url_params.len())
|
.got(self.url_params.len())
|
||||||
.expected(len));
|
.expected(len));
|
||||||
|
@ -160,7 +160,7 @@ impl<'de> Deserializer<'de> for PathDeserializer<'de> {
|
||||||
where
|
where
|
||||||
V: Visitor<'de>,
|
V: Visitor<'de>,
|
||||||
{
|
{
|
||||||
if self.url_params.len() < len {
|
if self.url_params.len() != len {
|
||||||
return Err(PathDeserializationError::wrong_number_of_parameters()
|
return Err(PathDeserializationError::wrong_number_of_parameters()
|
||||||
.got(self.url_params.len())
|
.got(self.url_params.len())
|
||||||
.expected(len));
|
.expected(len));
|
||||||
|
@ -773,20 +773,6 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_tuple_ignoring_additional_fields() {
|
|
||||||
let url_params = create_url_params(vec![
|
|
||||||
("a", "abc"),
|
|
||||||
("b", "true"),
|
|
||||||
("c", "1"),
|
|
||||||
("d", "false"),
|
|
||||||
]);
|
|
||||||
assert_eq!(
|
|
||||||
<(&str, bool, u32)>::deserialize(PathDeserializer::new(&url_params)).unwrap(),
|
|
||||||
("abc", true, 1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_map() {
|
fn test_parse_map() {
|
||||||
let url_params = create_url_params(vec![("a", "1"), ("b", "true"), ("c", "abc")]);
|
let url_params = create_url_params(vec![("a", "1"), ("b", "true"), ("c", "abc")]);
|
||||||
|
@ -813,6 +799,18 @@ mod tests {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_tuple_too_many_fields() {
|
||||||
|
test_parse_error!(
|
||||||
|
vec![("a", "abc"), ("b", "true"), ("c", "1"), ("d", "false"),],
|
||||||
|
(&str, bool, u32),
|
||||||
|
ErrorKind::WrongNumberOfParameters {
|
||||||
|
got: 4,
|
||||||
|
expected: 3,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wrong_number_of_parameters_error() {
|
fn test_wrong_number_of_parameters_error() {
|
||||||
test_parse_error!(
|
test_parse_error!(
|
||||||
|
|
|
@ -747,6 +747,33 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[crate::test]
|
||||||
|
async fn tuple_param_matches_exactly() {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Tuple(String, String);
|
||||||
|
|
||||||
|
let app = Router::new()
|
||||||
|
.route("/foo/:a/:b/:c", get(|_: Path<(String, String)>| async {}))
|
||||||
|
.route("/bar/:a/:b/:c", get(|_: Path<Tuple>| async {}));
|
||||||
|
|
||||||
|
let client = TestClient::new(app);
|
||||||
|
|
||||||
|
let res = client.get("/foo/a/b/c").await;
|
||||||
|
assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
assert_eq!(
|
||||||
|
res.text().await,
|
||||||
|
"Wrong number of path arguments for `Path`. Expected 2 but got 3",
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = client.get("/bar/a/b/c").await;
|
||||||
|
assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
assert_eq!(
|
||||||
|
res.text().await,
|
||||||
|
"Wrong number of path arguments for `Path`. Expected 2 but got 3",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[crate::test]
|
#[crate::test]
|
||||||
async fn deserialize_into_vec_of_tuples() {
|
async fn deserialize_into_vec_of_tuples() {
|
||||||
let app = Router::new().route(
|
let app = Router::new().route(
|
||||||
|
|
Loading…
Reference in a new issue