volo_http/error/
server.rs1use std::{error::Error, fmt};
4
5use http::StatusCode;
6
7use crate::{response::Response, server::IntoResponse};
8
9#[derive(Debug)]
11#[non_exhaustive]
12pub enum ExtractBodyError {
13 Generic(GenericRejectionError),
16 String(simdutf8::basic::Utf8Error),
19 #[cfg(feature = "json")]
21 Json(crate::utils::json::Error),
22 #[cfg(feature = "form")]
24 Form(serde_urlencoded::de::Error),
25}
26
27impl fmt::Display for ExtractBodyError {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 f.write_str("failed to extract ")?;
30 match self {
31 Self::Generic(e) => write!(f, "data: {e}"),
32 Self::String(e) => write!(f, "string: {e}"),
33 #[cfg(feature = "json")]
34 Self::Json(e) => write!(f, "json: {e}"),
35 #[cfg(feature = "form")]
36 Self::Form(e) => write!(f, "form: {e}"),
37 }
38 }
39}
40
41impl Error for ExtractBodyError {
42 fn source(&self) -> Option<&(dyn Error + 'static)> {
43 match self {
44 Self::Generic(e) => Some(e),
45 Self::String(e) => Some(e),
46 #[cfg(feature = "json")]
47 Self::Json(e) => Some(e),
48 #[cfg(feature = "form")]
49 Self::Form(e) => Some(e),
50 }
51 }
52}
53
54impl IntoResponse for ExtractBodyError {
55 fn into_response(self) -> Response {
56 let status = match self {
57 Self::Generic(e) => e.to_status_code(),
58 Self::String(_) => StatusCode::UNSUPPORTED_MEDIA_TYPE,
59 #[cfg(feature = "json")]
60 Self::Json(_) => StatusCode::BAD_REQUEST,
61 #[cfg(feature = "form")]
62 Self::Form(_) => StatusCode::BAD_REQUEST,
63 };
64
65 status.into_response()
66 }
67}
68
69#[derive(Debug)]
71#[non_exhaustive]
72pub enum GenericRejectionError {
73 BodyCollectionError,
75 InvalidContentType,
77}
78
79impl fmt::Display for GenericRejectionError {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 match self {
82 Self::BodyCollectionError => write!(f, "failed to collect the response body"),
83 Self::InvalidContentType => write!(f, "invalid content type"),
84 }
85 }
86}
87
88impl Error for GenericRejectionError {}
89
90impl GenericRejectionError {
91 pub fn to_status_code(&self) -> StatusCode {
93 match self {
94 Self::BodyCollectionError => StatusCode::INTERNAL_SERVER_ERROR,
95 Self::InvalidContentType => StatusCode::UNSUPPORTED_MEDIA_TYPE,
96 }
97 }
98}
99
100impl IntoResponse for GenericRejectionError {
101 fn into_response(self) -> Response {
102 self.to_status_code().into_response()
103 }
104}
105
106pub fn body_collection_error() -> ExtractBodyError {
108 ExtractBodyError::Generic(GenericRejectionError::BodyCollectionError)
109}
110
111pub fn invalid_content_type() -> ExtractBodyError {
113 ExtractBodyError::Generic(GenericRejectionError::InvalidContentType)
114}