mirror of
https://github.com/tokio-rs/axum.git
synced 2026-09-03 00:00:07 +02:00
Extend custom rejection examples (#1276)
* examples: Created new `error-handling` example
* examples(error-handling): Add error codes and responses
* examples(error-handling): `custom_extractor`
* examples(error-handling): `derive_from_request`
* examples(error-handling): Using POST instead of GET
* examples(error-handling): Using `thiserror` for `derive_from_request`
* examples(error-handling): Using `snake-case` for routes
* revert(error-handling): Use `From` impl instead of `thiserror`
refs: 3533d96215
* examples(error-handling): Removed chrono
* examples: merged `error-handling` and `customize-extractor-error`
* examples(customize-extractor-error): Improved error codes
* examples(customize-extractor-error): rustfmt
* examples(customize-extractor-error): Removed `matched-path` feature
Co-authored-by: David Pedersen <[email protected]>
* examples(customize-extractor-error): added `publish=false` to `Cargo.toml`
Co-authored-by: David Pedersen <[email protected]>
* examples(customize-extractor-error): Fix env filter
* examples(customize-extractor-error): Added README
* examples(customize-extractor-error): Added `with_rejection` comments
* examples(customize-extractor-error): Added `custom_extractor` comments
* examples(customize-extractor-error):Typo on `with_rejection`
* examples(customize-extractor-error): Added `boilerplate` con to `custom_extractor`
* examples(customize-extractor-error): Added `derive_from_request` comments
* examples(customize-extractor-error): typo impossible
* examples(customize-extractor-error): typos
* examples(customize-extractor-error): replaced `extensions` with `extract`
* examples(customize-extractor-error): typo `from`
Co-authored-by: David Pedersen <[email protected]>
Co-authored-by: David Pedersen <[email protected]>
This commit is contained in:
co-authored by
David Pedersen
parent
18dd830b84
commit
789f51ba1a
@@ -0,0 +1,57 @@
|
||||
//! Uses `axum_extra::extract::WithRejection` to transform one rejection into
|
||||
//! another
|
||||
//!
|
||||
//! + Easy learning curve: `WithRejection` acts as a wrapper for another
|
||||
//! already existing extractor. You only need to provide a `From` impl
|
||||
//! between the original rejection type and the target rejection. Crates like
|
||||
//! `thiserror` can provide such conversion using derive macros. See
|
||||
//! [`thiserror`]
|
||||
//! - Verbose types: types become much larger, which makes them difficult to
|
||||
//! read. Current limitations on type aliasing makes impossible to destructure
|
||||
//! a type alias. See [#1116]
|
||||
//!
|
||||
//! [`thiserror`]: https://crates.io/crates/thiserror
|
||||
//! [#1116]: https://github.com/tokio-rs/axum/issues/1116#issuecomment-1186197684
|
||||
|
||||
use axum::{extract::rejection::JsonRejection, http::StatusCode, response::IntoResponse, Json};
|
||||
use axum_extra::extract::WithRejection;
|
||||
use serde_json::{json, Value};
|
||||
use thiserror::Error;
|
||||
|
||||
pub async fn handler(
|
||||
// `WitRejection` will extract `Json<Value>` from the request. If it fails,
|
||||
// `JsonRejection` will be transform into `ApiError` and returned as response
|
||||
// to the client.
|
||||
//
|
||||
// The second constructor argument is not meaningful and can be safely ignored
|
||||
WithRejection(Json(value), _): WithRejection<Json<Value>, ApiError>,
|
||||
) -> impl IntoResponse {
|
||||
Json(dbg!(value))
|
||||
}
|
||||
|
||||
// We derive `thiserror::Error`
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ApiError {
|
||||
// The `#[from]` attribute generates `From<JsonRejection> for ApiError`
|
||||
// implementation. See `thiserror` docs for more information
|
||||
#[error(transparent)]
|
||||
JsonExtractorRejection(#[from] JsonRejection),
|
||||
}
|
||||
// We implement `IntoResponse` so ApiError can be used as a response
|
||||
impl IntoResponse for ApiError {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
let payload = json!({
|
||||
"message": self.to_string(),
|
||||
"origin": "with_rejection"
|
||||
});
|
||||
let code = match self {
|
||||
ApiError::JsonExtractorRejection(x) => match x {
|
||||
JsonRejection::JsonDataError(_) => StatusCode::UNPROCESSABLE_ENTITY,
|
||||
JsonRejection::JsonSyntaxError(_) => StatusCode::BAD_REQUEST,
|
||||
JsonRejection::MissingJsonContentType(_) => StatusCode::UNSUPPORTED_MEDIA_TYPE,
|
||||
_ => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
},
|
||||
};
|
||||
(code, Json(payload)).into_response()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user