svix_webhook_with_clone/
error.rs1use std::fmt;
5
6use http_body_util::BodyExt;
7use hyper::body::Incoming;
8
9use crate::http1_to_02_status_code;
10
11pub type Result<T> = std::result::Result<T, Error>;
12
13#[derive(Debug, Clone)]
15pub enum Error {
16 Generic(String),
18 Http(HttpErrorContent<crate::models::HttpErrorOut>),
20 Validation(HttpErrorContent<crate::models::HttpValidationError>),
22}
23
24impl Error {
25 pub(crate) fn generic(err: impl std::error::Error) -> Self {
26 Self::Generic(format!("{err:?}"))
27 }
28
29 pub(crate) async fn from_response(status_code: http1::StatusCode, body: Incoming) -> Self {
30 match body.collect().await {
31 Ok(collected) => {
32 let bytes = collected.to_bytes();
33 if status_code == http1::StatusCode::UNPROCESSABLE_ENTITY {
34 Self::Validation(HttpErrorContent {
35 status: http02::StatusCode::UNPROCESSABLE_ENTITY,
36 payload: serde_json::from_slice(&bytes).ok(),
37 })
38 } else {
39 Error::Http(HttpErrorContent {
40 status: http1_to_02_status_code(status_code),
41 payload: serde_json::from_slice(&bytes).ok(),
42 })
43 }
44 }
45 Err(e) => Self::Generic(e.to_string()),
46 }
47 }
48}
49
50impl From<Error> for String {
52 fn from(err: Error) -> Self {
53 err.to_string()
54 }
55}
56
57impl fmt::Display for Error {
58 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59 match self {
60 Error::Generic(s) => s.fmt(f),
61 Error::Http(e) => format!("Http error (status={}) {:?}", e.status, e.payload).fmt(f),
62 Error::Validation(e) => format!("Validation error {:?}", e.payload).fmt(f),
63 }
64 }
65}
66
67impl std::error::Error for Error {}
68
69#[derive(Debug, Clone)]
70pub struct HttpErrorContent<T> {
71 pub status: http02::StatusCode,
72 pub payload: Option<T>,
73}