svix_webhook_with_clone/
error.rs

1// SPDX-FileCopyrightText: © 2022 Svix Authors
2// SPDX-License-Identifier: MIT
3
4use 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/// The error type returned from the Svix API
14#[derive(Debug, Clone)]
15pub enum Error {
16    /// A generic error
17    Generic(String),
18    /// Http Error
19    Http(HttpErrorContent<crate::models::HttpErrorOut>),
20    /// Http Validation Error
21    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
50// TODO: Remove for v2.0 of the library (very uncommon impl for an error type)
51impl 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}