WithRejection<T, E> requires E to implement IntoResponse. If you forget that you get the familiar "handler not implemented" error and #[debug_handler] doesn't help:
use axum::extract::rejection::JsonRejection;
use axum::response::{IntoResponse, Response};
use axum::routing::{post, MethodRouter};
use axum::Json;
use axum_extra::extract::WithRejection;
#[tokio::main]
async fn main() {
let _: MethodRouter = post(send);
}
#[axum_macros::debug_handler]
pub async fn send(
_: WithRejection<Json<MessageSend>, ApiError>,
) -> Json<MessageSendResponse> {
Json(MessageSendResponse { id: "".to_string() })
}
#[derive(serde::Deserialize)]
pub struct MessageSend {
pub contents: String,
}
#[derive(serde::Serialize)]
pub struct MessageSendResponse {
pub id: String,
}
#[derive(Debug, thiserror::Error)]
pub enum ApiError {
#[error(transparent)]
JsonExtractorRejection(#[from] JsonRejection),
}
// no `impl IntoResponse for ApiError`
The error message is
error[E0277]: the trait bound `fn(WithRejection<Json<MessageSend>, ApiError>) -> impl Future<Output = Json<MessageSendResponse>> {send}: Handler<_, _, _>` is not satisfied
--> src/main.rs:9:32
|
9 | let _: MethodRouter = post(send);
| ---- ^^^^ the trait `Handler<_, _, _>` is not implemented for `fn(WithRejection<Json<MessageSend>, ApiError>) -> impl Future<Output = Json<MessageSendResponse>> {send}`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Handler<T, S, B>`:
<IntoHandler<H, T, S, B> as Handler<T, S, B>>
<Layered<L, H, T, S, B> as Handler<T, S, B>>
<Or<L, R, Lt, Rt, S, B> as Handler<(M, Lt, Rt), S, B>>
note: required by a bound in `post`
--> /Users/davidpdrsn/.cargo/registry/src/github.com-1ecc6299db9ec823/axum-0.6.0-rc.1/src/routing/method_routing.rs:404:1
|
404 | top_level_handler_fn!(post, POST);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `post`
= note: this error originates in the macro `top_level_handler_fn` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: the trait bound `WithRejection<Json<MessageSend>, ApiError>: FromRequest<(), Body, _>` is not satisfied
--> src/main.rs:14:8
|
14 | _: WithRejection<Json<MessageSend>, ApiError>,
| ^^^^^^^^^^^^^ the trait `FromRequest<(), Body, _>` is not implemented for `WithRejection<Json<MessageSend>, ApiError>`
|
= help: the trait `FromRequest<S, B>` is implemented for `WithRejection<E, R>`
note: required by a bound in `__axum_macros_check_send_0_from_request_check`
The generate code is
#[allow(warnings)]
fn __axum_macros_check_send_0_from_request_check<M>()
where
WithRejection<Json<MessageSend>, ApiError>:
::axum::extract::FromRequest<(), axum::body::Body, M> + Send,
{
}
#[allow(warnings)]
fn __axum_macros_check_send_0_from_request_call_check() {
__axum_macros_check_send_0_from_request_check();
}
For some reason the additional M type parameter changes rust's error message. If you remove that and instead generate
#[allow(warnings)]
fn __axum_macros_check_send_0_from_request_check()
where
WithRejection<Json<MessageSend>, ApiError>:
::axum::extract::FromRequest<(), axum::body::Body> + Send,
{
}
The error message becomes
error[E0277]: the trait bound `ApiError: IntoResponse` is not satisfied
--> src/main.rs:36:5
|
36 | / WithRejection<Json<MessageSend>, ApiError>:
37 | | ::axum::extract::FromRequest<(), axum::body::Body> + Send,
| |_________________________________________________________________^ the trait `IntoResponse` is not implemented for `ApiError`
|
We could look into this and see if its possible to improve this.
WithRejection<T, E>requiresEto implementIntoResponse. If you forget that you get the familiar "handler not implemented" error and#[debug_handler]doesn't help:The error message is
The generate code is
For some reason the additional
Mtype parameter changes rust's error message. If you remove that and instead generateThe error message becomes
We could look into this and see if its possible to improve this.