Attribute Macro axum::debug_handler
source · #[debug_handler]
macros
only.Expand description
Generates better error messages when applied handler functions.
While using axum
, you can get long error messages for simple mistakes. For example:
use axum::{routing::get, Router};
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(handler));
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
fn handler() -> &'static str {
"Hello, world"
}
You will get a long error message about function not implementing Handler
trait. But why
does this function not implement it? To figure it out, the debug_handler
macro can be used.
#[debug_handler]
fn handler() -> &'static str {
"Hello, world"
}
error: handlers must be async functions
--> main.rs:xx:1
|
xx | fn handler() -> &'static str {
| ^^
As the error message says, handler function needs to be async.
use axum::{routing::get, Router, debug_handler};
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(handler));
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
#[debug_handler]
async fn handler() -> &'static str {
"Hello, world"
}
Changing request body type
By default #[debug_handler]
assumes your request body type is axum::body::Body
. This will
work for most extractors but, for example, it wont work for Request<axum::body::BoxBody>
,
which only implements FromRequest<BoxBody>
and not FromRequest<Body>
.
To work around that the request body type can be customized like so:
use axum::{body::BoxBody, http::Request, debug_handler};
#[debug_handler(body = BoxBody)]
async fn handler(request: Request<BoxBody>) {}
Changing state type
By default #[debug_handler]
assumes your state type is ()
unless your handler has a
axum::extract::State
argument:
use axum::{debug_handler, extract::State};
#[debug_handler]
async fn handler(
// this makes `#[debug_handler]` use `AppState`
State(state): State<AppState>,
) {}
#[derive(Clone)]
struct AppState {}
If your handler takes multiple axum::extract::State
arguments or you need to otherwise
customize the state type you can set it with #[debug_handler(state = ...)]
:
use axum::{debug_handler, extract::{State, FromRef}};
#[debug_handler(state = AppState)]
async fn handler(
State(app_state): State<AppState>,
State(inner_state): State<InnerState>,
) {}
#[derive(Clone)]
struct AppState {
inner: InnerState,
}
#[derive(Clone)]
struct InnerState {}
impl FromRef<AppState> for InnerState {
fn from_ref(state: &AppState) -> Self {
state.inner.clone()
}
}
Limitations
This macro does not work for functions in an impl
block that don’t have a self
parameter:
use axum::{debug_handler, extract::Path};
struct App {}
impl App {
#[debug_handler]
async fn handler(Path(_): Path<String>) {}
}
This will yield an error similar to this:
error[E0425]: cannot find function `__axum_macros_check_handler_0_from_request_check` in this scope
Performance
This macro has no effect when compiled with the release profile. (eg. cargo build --release
)