mirror of
https://github.com/tokio-rs/axum.git
synced 2025-09-30 22:41:03 +00:00
105 lines
2.9 KiB
Rust
105 lines
2.9 KiB
Rust
use std::convert::Infallible;
|
|
|
|
use http::{Response, StatusCode};
|
|
use tower::BoxError;
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
#[non_exhaustive]
|
|
pub enum Error {
|
|
#[error("failed to deserialize the request body")]
|
|
DeserializeRequestBody(#[source] serde_json::Error),
|
|
|
|
#[error("failed to serialize the response body")]
|
|
SerializeResponseBody(#[source] serde_json::Error),
|
|
|
|
#[error("failed to consume the body")]
|
|
ConsumeRequestBody(#[source] hyper::Error),
|
|
|
|
#[error("URI contained no query string")]
|
|
QueryStringMissing,
|
|
|
|
#[error("failed to deserialize query string")]
|
|
DeserializeQueryString(#[source] serde_urlencoded::de::Error),
|
|
|
|
#[error("failed generating the response body")]
|
|
ResponseBody(#[source] BoxError),
|
|
|
|
#[error("some dynamic error happened")]
|
|
Dynamic(#[source] BoxError),
|
|
|
|
#[error("request extension of type `{type_name}` was not set")]
|
|
MissingExtension { type_name: &'static str },
|
|
|
|
#[error("`Content-Length` header is missing but was required")]
|
|
LengthRequired,
|
|
|
|
#[error("response body was too large")]
|
|
PayloadTooLarge,
|
|
|
|
#[error("response failed with status {0}")]
|
|
Status(StatusCode),
|
|
|
|
#[error("invalid URL param. Expected something of type `{type_name}`")]
|
|
InvalidUrlParam { type_name: &'static str },
|
|
|
|
#[error("unknown URL param `{0}`")]
|
|
UnknownUrlParam(String),
|
|
|
|
#[error("response body didn't contain valid UTF-8")]
|
|
InvalidUtf8,
|
|
}
|
|
|
|
impl From<BoxError> for Error {
|
|
fn from(err: BoxError) -> Self {
|
|
match err.downcast::<Error>() {
|
|
Ok(err) => *err,
|
|
Err(err) => Error::Dynamic(err),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<Infallible> for Error {
|
|
fn from(err: Infallible) -> Self {
|
|
match err {}
|
|
}
|
|
}
|
|
|
|
pub(crate) fn handle_error<B>(error: Error) -> Result<Response<B>, Error>
|
|
where
|
|
B: Default,
|
|
{
|
|
fn make_response<B>(status: StatusCode) -> Result<Response<B>, Error>
|
|
where
|
|
B: Default,
|
|
{
|
|
let mut res = Response::new(B::default());
|
|
*res.status_mut() = status;
|
|
Ok(res)
|
|
}
|
|
|
|
match error {
|
|
Error::DeserializeRequestBody(_)
|
|
| Error::QueryStringMissing
|
|
| Error::DeserializeQueryString(_)
|
|
| Error::InvalidUrlParam { .. }
|
|
| Error::InvalidUtf8 => make_response(StatusCode::BAD_REQUEST),
|
|
|
|
Error::Status(status) => make_response(status),
|
|
|
|
Error::LengthRequired => make_response(StatusCode::LENGTH_REQUIRED),
|
|
Error::PayloadTooLarge => make_response(StatusCode::PAYLOAD_TOO_LARGE),
|
|
|
|
Error::MissingExtension { .. }
|
|
| Error::SerializeResponseBody(_)
|
|
| Error::UnknownUrlParam(_) => make_response(StatusCode::INTERNAL_SERVER_ERROR),
|
|
|
|
Error::Dynamic(err) => match err.downcast::<Error>() {
|
|
Ok(err) => Err(*err),
|
|
Err(err) => Err(Error::Dynamic(err)),
|
|
},
|
|
|
|
err @ Error::ConsumeRequestBody(_) => Err(err),
|
|
err @ Error::ResponseBody(_) => Err(err),
|
|
}
|
|
}
|