Document "debugging handler type errors" on Handler (#1024)

This commit is contained in:
David Pedersen 2022-05-11 20:56:57 +02:00 committed by GitHub
parent 08cbade3cb
commit 0b856b938f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 36 deletions

View file

@ -0,0 +1,37 @@
## Debugging handler type errors
For a function to be used as a handler it must implement the [`Handler`] trait.
axum provides blanket implementations for functions that:
- Are `async fn`s.
- Take no more than 16 arguments that all implement [`FromRequest`].
- Returns something that implements [`IntoResponse`].
- If a closure is used it must implement `Clone + Send` and be
`'static`.
- Returns a future that is `Send`. The most common way to accidentally make a
future `!Send` is to hold a `!Send` type across an await.
Unfortunately Rust gives poor error messages if you try to use a function
that doesn't quite match what's required by [`Handler`].
You might get an error like this:
```not_rust
error[E0277]: the trait bound `fn(bool) -> impl Future {handler}: Handler<_, _>` is not satisfied
--> src/main.rs:13:44
|
13 | let app = Router::new().route("/", get(handler));
| ^^^^^^^ the trait `Handler<_, _>` is not implemented for `fn(bool) -> impl Future {handler}`
|
::: axum/src/handler/mod.rs:116:8
|
116 | H: Handler<T, B>,
| ------------- required by this bound in `axum::routing::get`
```
This error doesn't tell you _why_ your function doesn't implement
[`Handler`]. It's possible to improve the error with the [`debug_handler`]
proc-macro from the [axum-macros] crate.
[axum-macros]: https://docs.rs/axum-macros
[`debug_handler`]: https://docs.rs/axum-macros/latest/axum_macros/attr.debug_handler.html

View file

@ -33,42 +33,7 @@
//! }
//! ```
//!
//! ## Debugging handler type errors
//!
//! For a function to be used as a handler it must implement the [`Handler`] trait.
//! axum provides blanket implementations for functions that:
//!
//! - Are `async fn`s.
//! - Take no more than 16 arguments that all implement [`FromRequest`].
//! - Returns something that implements [`IntoResponse`].
//! - If a closure is used it must implement `Clone + Send` and be
//! `'static`.
//! - Returns a future that is `Send`. The most common way to accidentally make a
//! future `!Send` is to hold a `!Send` type across an await.
//!
//! Unfortunately Rust gives poor error messages if you try to use a function
//! that doesn't quite match what's required by [`Handler`].
//!
//! You might get an error like this:
//!
//! ```not_rust
//! error[E0277]: the trait bound `fn(bool) -> impl Future {handler}: Handler<_, _>` is not satisfied
//! --> src/main.rs:13:44
//! |
//! 13 | let app = Router::new().route("/", get(handler));
//! | ^^^^^^^ the trait `Handler<_, _>` is not implemented for `fn(bool) -> impl Future {handler}`
//! |
//! ::: axum/src/handler/mod.rs:116:8
//! |
//! 116 | H: Handler<T, B>,
//! | ------------- required by this bound in `axum::routing::get`
//! ```
//!
//! This error doesn't tell you _why_ your function doesn't implement
//! [`Handler`]. It's possible to improve the error with the [`debug_handler`]
//! proc-macro from the [axum-macros] crate.
//!
//! [axum-macros]: https://docs.rs/axum-macros
#![doc = include_str!("../docs/debugging_handler_type_errors.md")]
use crate::{
body::{boxed, Body, Bytes, HttpBody},
@ -94,6 +59,8 @@ pub use self::into_service::IntoService;
/// implemented to closures of the right types.
///
/// See the [module docs](crate::handler) for more details.
///
#[doc = include_str!("../docs/debugging_handler_type_errors.md")]
pub trait Handler<T, B = Body>: Clone + Send + Sized + 'static {
/// The type of future calling this handler returns.
type Future: Future<Output = Response> + Send + 'static;