Expand description
Async functions that can be used to handle requests.
In axum a “handler” is an async function that accepts zero or more “extractors” as arguments and returns something that can be converted into a response.
Handlers are where your application logic lives and axum applications are built by routing between handlers.
Some examples of handlers:
use axum::{body::Bytes, http::StatusCode};
// Handler that immediately returns an empty `200 OK` response.
async fn unit_handler() {}
// Handler that immediately returns an empty `200 OK` response with a plain
// text body.
async fn string_handler() -> String {
"Hello, World!".to_string()
}
// Handler that buffers the request body and returns it.
//
// This works because `Bytes` implements `FromRequest`
// and therefore can be used as an extractor.
//
// `String` and `StatusCode` both implement `IntoResponse` and
// therefore `Result<String, StatusCode>` also implements `IntoResponse`
async fn echo(body: Bytes) -> Result<String, StatusCode> {
if let Ok(string) = String::from_utf8(body.to_vec()) {
Ok(string)
} else {
Err(StatusCode::BAD_REQUEST)
}
}
Instead of a direct StatusCode
, it makes sense to use intermediate error type
that can ultimately be converted to Response
. This allows using ?
operator
in handlers. See those examples:
anyhow-error-response
for generic boxed errorserror-handling
for application-specific detailed errors
§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
Send
.- All except the last argument implement
FromRequestParts
. - The last argument implements
FromRequest
.
- All except the last argument implement
- 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:
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.
Modules§
- Handler future types.
Structs§
Traits§
- Trait for async functions that can be used to handle requests.
- Extension trait for
Handler
s that don’t have state.