Check for multiple body extractors in debug_handler (#1036)

* Check for multiple body extractors in `debug_handler`

* changelog link
This commit is contained in:
David Pedersen 2022-05-16 15:11:40 +01:00 committed by GitHub
parent 05529c8efc
commit 7d88bd3a66
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 76 additions and 26 deletions

View file

@ -9,8 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **added:** In `debug_handler`, check if `Request` is used as non-final extractor ([#1035])
- **added:** In `debug_handler`, check if multiple `Path` extractors are used ([#1035])
- **added:** In `debug_handler`, check if multiple body extractors are used ([#1036])
[#1035]: https://github.com/tokio-rs/axum/pull/1035
[#1036]: https://github.com/tokio-rs/axum/pull/1036
# 0.2.1 (10. May, 2022)

View file

@ -6,6 +6,7 @@ pub(crate) fn expand(attr: Attrs, item_fn: ItemFn) -> TokenStream {
let check_extractor_count = check_extractor_count(&item_fn);
let check_request_last_extractor = check_request_last_extractor(&item_fn);
let check_path_extractor = check_path_extractor(&item_fn);
let check_multiple_body_extractors = check_multiple_body_extractors(&item_fn);
let check_inputs_impls_from_request = check_inputs_impls_from_request(&item_fn, &attr.body_ty);
let check_output_impls_into_response = check_output_impls_into_response(&item_fn);
@ -16,6 +17,7 @@ pub(crate) fn expand(attr: Attrs, item_fn: ItemFn) -> TokenStream {
#check_extractor_count
#check_request_last_extractor
#check_path_extractor
#check_multiple_body_extractors
#check_inputs_impls_from_request
#check_output_impls_into_response
#check_future_send
@ -124,6 +126,32 @@ fn check_path_extractor(item_fn: &ItemFn) -> TokenStream {
}
}
fn check_multiple_body_extractors(item_fn: &ItemFn) -> TokenStream {
let body_extractors = extractor_idents(item_fn)
.filter(|(_, _, ident)| {
*ident == "String"
|| *ident == "Bytes"
|| *ident == "Json"
|| *ident == "RawBody"
|| *ident == "BodyStream"
|| *ident == "Multipart"
|| *ident == "Request"
})
.collect::<Vec<_>>();
if body_extractors.len() > 1 {
body_extractors
.into_iter()
.map(|(_, arg, _)| {
syn::Error::new_spanned(arg, "Only one body extractor can be applied")
.to_compile_error()
})
.collect()
} else {
quote! {}
}
}
fn check_inputs_impls_from_request(item_fn: &ItemFn, body_ty: &Type) -> TokenStream {
if !item_fn.sig.generics.params.is_empty() {
return syn::Error::new_spanned(

View file

@ -0,0 +1,7 @@
use axum_macros::debug_handler;
use axum::body::Bytes;
#[debug_handler]
async fn handler(_: String, _: Bytes) {}
fn main() {}

View file

@ -0,0 +1,11 @@
error: Only one body extractor can be applied
--> tests/debug_handler/fail/multiple_body_extractors.rs:5:18
|
5 | async fn handler(_: String, _: Bytes) {}
| ^^^^^^^^^
error: Only one body extractor can be applied
--> tests/debug_handler/fail/multiple_body_extractors.rs:5:29
|
5 | async fn handler(_: String, _: Bytes) {}
| ^^^^^^^^

View file

@ -1,24 +1,25 @@
use axum_macros::debug_handler;
use axum::http::Uri;
#[debug_handler]
async fn handler(
e1: String,
e2: String,
e3: String,
e4: String,
e5: String,
e6: String,
e7: String,
e8: String,
e9: String,
e10: String,
e11: String,
e12: String,
e13: String,
e14: String,
e15: String,
e16: String,
e17: String,
e1: Uri,
e2: Uri,
e3: Uri,
e4: Uri,
e5: Uri,
e6: Uri,
e7: Uri,
e8: Uri,
e9: Uri,
e10: Uri,
e11: Uri,
e12: Uri,
e13: Uri,
e14: Uri,
e15: Uri,
e16: Uri,
e17: Uri,
) {}
fn main() {}

View file

@ -1,11 +1,11 @@
error: Handlers cannot take more than 16 arguments. Use `(a, b): (ExtractorA, ExtractorA)` to further nest extractors
--> tests/debug_handler/fail/too_many_extractors.rs:5:5
--> tests/debug_handler/fail/too_many_extractors.rs:6:5
|
5 | / e1: String,
6 | | e2: String,
7 | | e3: String,
8 | | e4: String,
6 | / e1: Uri,
7 | | e2: Uri,
8 | | e3: Uri,
9 | | e4: Uri,
... |
20 | | e16: String,
21 | | e17: String,
| |________________^
21 | | e16: Uri,
22 | | e17: Uri,
| |_____________^

View file

@ -1,6 +1,7 @@
use axum_macros::debug_handler;
use axum::http::{Method, Uri};
#[debug_handler]
async fn handler(_one: String, _two: String, _three: String) {}
async fn handler(_one: Method, _two: Uri, _three: String) {}
fn main() {}