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:
Altair Bueno
2022-08-19 13:11:03 +00:00
committed by GitHub
co-authored by David Pedersen
parent 18dd830b84
commit 789f51ba1a
6 changed files with 219 additions and 74 deletions
@@ -0,0 +1,60 @@
//! Uses `axum_macros::FromRequest` to wrap another extractor and customize the
//! rejection
//!
//! + Easy learning curve: Deriving `FromRequest` generates a `FromRequest`
//! implementation for your type using another 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.
//! - Boilerplate: Requires deriving `FromRequest` for every custom rejection
//! - There are some known limitations: [FromRequest#known-limitations]
//!
//! [`thiserror`]: https://crates.io/crates/thiserror
//! [FromRequest#known-limitations]: https://docs.rs/axum-macros/*/axum_macros/derive.FromRequest.html#known-limitations
use axum::{extract::rejection::JsonRejection, http::StatusCode, response::IntoResponse};
use axum_macros::FromRequest;
use serde_json::{json, Value};
pub async fn handler(Json(value): Json<Value>) -> impl IntoResponse {
Json(dbg!(value));
}
// create an extractor that internally uses `axum::Json` but has a custom rejection
#[derive(FromRequest)]
#[from_request(via(axum::Json), rejection(ApiError))]
pub struct Json<T>(T);
// We create our own rejection type
#[derive(Debug)]
pub struct ApiError {
code: StatusCode,
message: String,
}
// We implement `From<JsonRejection> for ApiError`
impl From<JsonRejection> for ApiError {
fn from(rejection: JsonRejection) -> Self {
let code = match rejection {
JsonRejection::JsonDataError(_) => StatusCode::UNPROCESSABLE_ENTITY,
JsonRejection::JsonSyntaxError(_) => StatusCode::BAD_REQUEST,
JsonRejection::MissingJsonContentType(_) => StatusCode::UNSUPPORTED_MEDIA_TYPE,
_ => StatusCode::INTERNAL_SERVER_ERROR,
};
Self {
code,
message: rejection.to_string(),
}
}
}
// 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.message,
"origin": "derive_from_request"
});
(self.code, axum::Json(payload)).into_response()
}
}