unc_jsonrpc_client/
errors.rs

1//! Error types.
2use std::io;
3
4use thiserror::Error;
5
6use unc_jsonrpc_primitives::errors::{RpcError, RpcErrorKind, RpcRequestValidationErrorKind};
7use unc_jsonrpc_primitives::message::{self, Message};
8
9/// Potential errors returned while sending a request to the RPC server.
10#[derive(Debug, Error)]
11pub enum JsonRpcTransportSendError {
12    /// Client is unable to serialize the request payload before sending it to the server.
13    #[error("error while serializing payload: [{0}]")]
14    PayloadSerializeError(io::Error),
15    /// Client is unable to send the request to the server.
16    #[error("error while sending payload: [{0}]")]
17    PayloadSendError(reqwest::Error),
18}
19
20/// Potential errors returned when the client has an issue parsing the response of a method call.
21#[derive(Debug, Error)]
22pub enum JsonRpcTransportHandlerResponseError {
23    /// Client fails to deserialize the result of a method call.
24    #[error("error while parsing method call result: [{0}]")]
25    ResultParseError(serde_json::Error),
26    /// Client fails to deserialize the error message returned from a method call.
27    #[error("error while parsing method call error message: [{0}]")]
28    ErrorMessageParseError(serde_json::Error),
29}
30
31/// Potential errors returned while receiving responses from an RPC server.
32#[derive(Debug, Error)]
33pub enum JsonRpcTransportRecvError {
34    /// Client receives a JSON RPC message body that isn't structured as a response.
35    #[error("unexpected server response: [{0:?}]")]
36    UnexpectedServerResponse(Message),
37    /// Client is unable to read the response from the RPC server.
38    #[error("error while reading response: [{0}]")]
39    PayloadRecvError(reqwest::Error),
40    /// The base response structure is malformed e.g. meta properties like RPC version are missing.
41    #[error("error while parsing server response: [{0:?}]")]
42    PayloadParseError(message::Broken),
43    /// Potential errors returned when the client has an issue parsing the response of a method call.
44    #[error(transparent)]
45    ResponseParseError(JsonRpcTransportHandlerResponseError),
46}
47
48/// Potential errors returned while sending requests to or receiving responses from the RPC server.
49#[derive(Debug, Error)]
50pub enum RpcTransportError {
51    /// Potential errors returned while sending a request to the RPC server.
52    #[error(transparent)]
53    SendError(JsonRpcTransportSendError),
54    /// Potential errors returned while receiving a response from an RPC server.
55    #[error(transparent)]
56    RecvError(JsonRpcTransportRecvError),
57}
58
59/// Unexpected status codes returned by the RPC server.
60#[derive(Debug, Error)]
61pub enum JsonRpcServerResponseStatusError {
62    /// The RPC client is unauthorized.
63    #[error("this client is unauthorized")]
64    Unauthorized,
65    /// The RPC client exceeds the rate limit by sending too many requests.
66    #[error("this client has exceeded the rate limit")]
67    TooManyRequests,
68    /// The RPC server returned a non-200 status code.
69    #[error("the server returned a non-OK (200) status code: [{status}]")]
70    Unexpected { status: reqwest::StatusCode },
71}
72
73/// Potential errors returned by the RPC server.
74#[derive(Debug, Error)]
75pub enum JsonRpcServerError<E> {
76    /// An invalid RPC method is called or the RPC methdo is unable to parse the provided arguments.
77    #[error("request validation error: [{0:?}]")]
78    RequestValidationError(RpcRequestValidationErrorKind),
79    /// RPC method call error.
80    #[error("handler error: [{0}]")]
81    HandlerError(E),
82    /// The RPC server returned an internal server error.
83    #[error("internal error: [{info:?}]")]
84    InternalError { info: Option<String> },
85    /// The RPC server returned a response without context i.e. a response the client doesn't expect.
86    #[error("error response lacks context: {0}")]
87    NonContextualError(RpcError),
88    /// Unexpected status codes returned by the RPC server.
89    #[error(transparent)]
90    ResponseStatusError(JsonRpcServerResponseStatusError),
91}
92
93/// Potential errors returned by the RPC client.
94#[derive(Debug, Error)]
95pub enum JsonRpcError<E> {
96    /// Potential errors returned while sending requests to or receiving responses from the RPC server.
97    #[error(transparent)]
98    TransportError(RpcTransportError),
99    /// Potential errors returned by the RPC server.
100    #[error(transparent)]
101    ServerError(JsonRpcServerError<E>),
102}
103
104impl<E> JsonRpcError<E> {
105    pub fn handler_error(&self) -> Option<&E> {
106        if let Self::ServerError(JsonRpcServerError::HandlerError(err)) = self {
107            return Some(err);
108        }
109        None
110    }
111}
112
113impl<E: super::methods::RpcHandlerError> From<RpcError> for JsonRpcError<E> {
114    fn from(err: RpcError) -> Self {
115        let mut handler_parse_error = None;
116        match err.error_struct {
117            Some(RpcErrorKind::HandlerError(ref handler_error)) => {
118                match E::parse(handler_error.clone()) {
119                    Ok(handler_error) => {
120                        return JsonRpcError::ServerError(JsonRpcServerError::HandlerError(
121                            handler_error,
122                        ))
123                    }
124                    Err(err) => {
125                        handler_parse_error.replace(err);
126                    }
127                }
128            }
129            Some(RpcErrorKind::RequestValidationError(err)) => {
130                return JsonRpcError::ServerError(JsonRpcServerError::RequestValidationError(err));
131            }
132            Some(RpcErrorKind::InternalError(err)) => {
133                return JsonRpcError::ServerError(JsonRpcServerError::InternalError {
134                    info: err["info"]["error_message"]
135                        .as_str()
136                        .map(|info| info.to_string()),
137                })
138            }
139            None => {}
140        }
141        if let Some(ref raw_err_data) = err.data {
142            match E::parse_legacy_error(raw_err_data.clone()) {
143                Some(Ok(handler_error)) => {
144                    return JsonRpcError::ServerError(JsonRpcServerError::HandlerError(
145                        handler_error,
146                    ))
147                }
148                Some(Err(err)) => {
149                    handler_parse_error.replace(err);
150                }
151                None => {}
152            }
153        }
154        if let Some(err) = handler_parse_error {
155            return JsonRpcError::TransportError(RpcTransportError::RecvError(
156                JsonRpcTransportRecvError::ResponseParseError(
157                    JsonRpcTransportHandlerResponseError::ErrorMessageParseError(err),
158                ),
159            ));
160        }
161        JsonRpcError::ServerError(JsonRpcServerError::NonContextualError(err))
162    }
163}