Nested custom extractor with pair as rejection #1220
-
Bug ReportGreeting! I'm trying to make custom error response handlers and to do that, I started writing extractor wrappers like here: https://github.com/tokio-rs/axum/blob/main/examples/customize-extractor-error/src/main.rs Version➜ playground3 git:(master) ✗ cargo tree | grep axum
├── axum v0.5.13
│ ├── axum-core v0.2.7
│ ├── axum-macros v0.2.3 (proc-macro) DescriptionI tried this code: use axum::{
body::HttpBody,
extract::{
rejection::ContentLengthLimitRejection, ContentLengthLimit, FromRequest, RequestParts,
},
http::StatusCode,
BoxError, Json,
};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::{json, Value as JsonValue};
use std::fmt;
struct ContentLengthLimitWrapper<T, const N: u64>(pub T);
struct JsonWrapper<T>(pub T);
#[async_trait::async_trait]
impl<T, B, const N: u64> FromRequest<B> for ContentLengthLimitWrapper<T, N>
where
T: FromRequest<B>,
ContentLengthLimitRejection<<T as FromRequest<B>>::Rejection>: fmt::Display,
B: Send,
{
type Rejection = (StatusCode, Json<JsonValue>);
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
match ContentLengthLimit::<T, N>::from_request(req).await {
Ok(ContentLengthLimit(data)) => Ok(Self(data)),
Err(err) => Err((
StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({"description": err.to_string()})),
)),
}
}
}
#[async_trait::async_trait]
impl<T, B> FromRequest<B> for JsonWrapper<T>
where
T: DeserializeOwned,
B: HttpBody + Send,
B::Data: Send,
B::Error: Into<BoxError>,
{
type Rejection = (StatusCode, Json<JsonValue>);
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
match Json::<T>::from_request(req).await {
Ok(Json(data)) => Ok(Self(data)),
Err(err) => Err((
StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({"description": err.to_string()})),
)),
}
}
}
#[derive(Serialize, Deserialize)]
struct Parameters {
name: Box<str>,
}
#[axum::debug_handler]
async fn handler(
ContentLengthLimitWrapper(JsonWrapper(param)): ContentLengthLimitWrapper<
JsonWrapper<Parameters>,
10,
>,
) -> Result<Json<JsonValue>, (StatusCode, Json<JsonValue>)> {
Ok(Json(json!({
"msg": "ok",
"parameters": param,
})))
}
fn main() {
let _ = handler;
} But got error: error[E0277]: `(axum::http::StatusCode, axum::Json<serde_json::Value>)` doesn't implement `std::fmt::Display`
--> src/main.rs:64:52
|
64 | ContentLengthLimitWrapper(JsonWrapper(param)): ContentLengthLimitWrapper<
| ^^^^^^^^^^^^^^^^^^^^^^^^^ `(axum::http::StatusCode, axum::Json<serde_json::Value>)` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `(axum::http::StatusCode, axum::Json<serde_json::Value>)`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
= help: the trait `axum::extract::FromRequest<B>` is implemented for `ContentLengthLimitWrapper<T, N>`
= note: required because of the requirements on the impl of `std::fmt::Display` for `axum::extract::rejection::ContentLengthLimitRejection<(axum::http::StatusCode, axum::Json<serde_json::Value>)>`
note: required because of the requirements on the impl of `axum::extract::FromRequest<axum::body::Body>` for `ContentLengthLimitWrapper<JsonWrapper<Parameters>, 10_u64>`
--> src/main.rs:17:26
|
17 | impl<T, B, const N: u64> FromRequest<B> for ContentLengthLimitWrapper<T, N>
| ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: see issue #48214 And I can't get from it comes from, because |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
With what you've written |
Beta Was this translation helpful? Give feedback.
With what you've written
ContentLengthLimitWrapper
requires the inner extractor's rejection to implementDisplay
, which(StatusCode, Json<JsonValue>)
does not. That isJsonWrapper<Parameters>
's rejection.