iota_graphql_rpc/
error.rs1use async_graphql::{ErrorExtensionValues, ErrorExtensions, Pos, Response, ServerError};
6use async_graphql_axum::GraphQLResponse;
7use iota_indexer::errors::IndexerError;
8use iota_names::error::IotaNamesError;
9
10pub(crate) mod code {
14 pub const BAD_REQUEST: &str = "BAD_REQUEST";
15 pub const BAD_USER_INPUT: &str = "BAD_USER_INPUT";
16 pub const INTERNAL_SERVER_ERROR: &str = "INTERNAL_SERVER_ERROR";
17 pub const REQUEST_TIMEOUT: &str = "REQUEST_TIMEOUT";
18 pub const UNKNOWN: &str = "UNKNOWN";
19}
20
21pub(crate) fn graphql_error_response(code: &str, message: impl Into<String>) -> GraphQLResponse {
29 let error = graphql_error(code, message);
30 Response::from_errors(error.into()).into()
31}
32
33pub(crate) fn graphql_error(code: &str, message: impl Into<String>) -> ServerError {
38 let mut ext = ErrorExtensionValues::default();
39 ext.set("code", code);
40
41 ServerError {
42 message: message.into(),
43 source: None,
44 locations: vec![],
45 path: vec![],
46 extensions: Some(ext),
47 }
48}
49
50pub(crate) fn graphql_error_at_pos(
51 code: &str,
52 message: impl Into<String>,
53 pos: Pos,
54) -> ServerError {
55 let mut ext = ErrorExtensionValues::default();
56 ext.set("code", code);
57
58 ServerError {
59 message: message.into(),
60 source: None,
61 locations: vec![pos],
62 path: vec![],
63 extensions: Some(ext),
64 }
65}
66
67#[derive(Clone, Debug, thiserror::Error)]
68#[non_exhaustive]
69pub enum Error {
70 #[error("Unsupported protocol version requested. Min supported: {0}, max supported: {1}")]
71 ProtocolVersionUnsupported(u64, u64),
72 #[error("'first' and 'last' must not be used together")]
73 CursorNoFirstLast,
74 #[error("Connection's page size of {0} exceeds max of {1}")]
75 PageTooLarge(u64, u32),
76 #[error("{0}")]
78 Client(String),
79 #[error("Internal error occurred while processing request: {0}")]
80 Internal(String),
81 #[error(transparent)]
82 IotaNames(#[from] IotaNamesError),
83}
84
85impl ErrorExtensions for Error {
86 fn extend(&self) -> async_graphql::Error {
87 async_graphql::Error::new(format!("{}", self)).extend_with(|_err, e| match self {
88 Error::CursorNoFirstLast
89 | Error::PageTooLarge(_, _)
90 | Error::ProtocolVersionUnsupported(_, _)
91 | Error::Client(_) => {
92 e.set("code", code::BAD_USER_INPUT);
93 }
94 Error::Internal(_) => {
95 e.set("code", code::INTERNAL_SERVER_ERROR);
96 }
97 Error::IotaNames(_) => {
98 e.set("code", code::BAD_REQUEST);
99 }
100 })
101 }
102}
103
104impl From<IndexerError> for Error {
105 fn from(e: IndexerError) -> Self {
106 Error::Internal(e.to_string())
107 }
108}