iota_rest_kv/
errors.rs

1// Copyright (c) 2025 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4//! This module includes the error types the REST API sends back to the client.
5
6use axum::{
7    Json,
8    http::StatusCode,
9    response::{IntoResponse, Response},
10};
11use serde::Serialize;
12use thiserror::Error;
13
14/// An Error type which represents the possible errors the REST API server can
15/// send back to the client.
16#[derive(Error, Debug)]
17pub enum ApiError {
18    #[error("bad request: {0}")]
19    BadRequest(String),
20    #[error("not found")]
21    NotFound,
22    #[error("internal server error")]
23    InternalServerError,
24}
25
26impl From<anyhow::Error> for ApiError {
27    fn from(err: anyhow::Error) -> Self {
28        tracing::error!("internal server error: {err}");
29        ApiError::InternalServerError
30    }
31}
32
33impl IntoResponse for ApiError {
34    fn into_response(self) -> Response {
35        let status_code = match self {
36            ApiError::BadRequest(_) => StatusCode::BAD_REQUEST,
37            ApiError::NotFound => StatusCode::NOT_FOUND,
38            ApiError::InternalServerError => StatusCode::INTERNAL_SERVER_ERROR,
39        };
40
41        let body = Json(ErrorResponse {
42            error_code: status_code.as_u16().to_string(),
43            error_message: self.to_string(),
44        });
45
46        (status_code, body).into_response()
47    }
48}
49
50/// Describes the response body of a unsuccessful HTTP request.
51#[derive(Clone, Debug, Serialize)]
52pub(crate) struct ErrorResponse {
53    error_code: String,
54    error_message: String,
55}