riftenlabs-indexer/src/rpc/err.rs

122 lines
3.9 KiB
Rust
Raw Normal View History

2025-02-15 09:15:22 +01:00
// Copyright (C) 2024 Riften Labs AS
//
// This software is licensed under the GNU Affero General Public License (AGPL), version 3.0 or later.
// A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/agpl-3.0.html
use rocket::{http::Status, response::status::Custom, serde::json::Json};
use serde_json::{json, Value};
use std::fmt;
2025-02-14 20:43:51 +01:00
use super::response::CachedJson;
/// Standard API result type with JSON-formatted errors (without caching headers)
#[allow(dead_code)]
pub type ApiResult<T> = Result<Json<T>, Custom<Json<Value>>>;
/// API result type with Cache-Control headers for cacheable responses
pub type CachedApiResult<T> = Result<CachedJson<T>, Custom<Json<Value>>>;
/// API error codes for consistent error responses
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ApiErrorCode {
// 400 Bad Request codes
InvalidTimestamp,
InvalidTokenId,
InvalidPoolId,
InvalidTxid,
InvalidParameters,
InvalidTimeRange,
InvalidStepsize,
MissingParameters,
MissingCategory,
TooManyIntervals,
FutureTimestamp,
// 404 Not Found codes
PriceNotFound,
PoolNotFound,
// 500 Internal Server Error codes
InternalError,
// 503 Service Unavailable codes
CacheWarming,
}
impl fmt::Display for ApiErrorCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
// 400 codes
Self::InvalidTimestamp => "INVALID_TIMESTAMP",
Self::InvalidTokenId => "INVALID_TOKEN_ID",
Self::InvalidPoolId => "INVALID_POOL_ID",
Self::InvalidTxid => "INVALID_TXID",
Self::InvalidParameters => "INVALID_PARAMETERS",
Self::InvalidTimeRange => "INVALID_TIME_RANGE",
Self::InvalidStepsize => "INVALID_STEPSIZE",
Self::MissingParameters => "MISSING_PARAMETERS",
Self::MissingCategory => "MISSING_CATEGORY",
Self::TooManyIntervals => "TOO_MANY_INTERVALS",
Self::FutureTimestamp => "FUTURE_TIMESTAMP",
// 404 codes
Self::PriceNotFound => "PRICE_NOT_FOUND",
Self::PoolNotFound => "POOL_NOT_FOUND",
// 500 codes
Self::InternalError => "INTERNAL_ERROR",
// 503 codes
Self::CacheWarming => "CACHE_WARMING",
};
write!(f, "{s}")
}
}
/// Create a 400 Bad Request error with JSON body
pub fn bad_request(code: ApiErrorCode, message: &str) -> Custom<Json<Value>> {
Custom(
Status::BadRequest,
Json(json!({
"error": { "code": code.to_string(), "message": message }
})),
)
}
/// Create a 404 Not Found error with JSON body
pub fn not_found(code: ApiErrorCode, message: &str) -> Custom<Json<Value>> {
Custom(
Status::NotFound,
Json(json!({
"error": { "code": code.to_string(), "message": message }
})),
)
}
/// Create a 500 Internal Server Error with JSON body
pub fn internal_error(message: &str) -> Custom<Json<Value>> {
Custom(
Status::InternalServerError,
Json(json!({
"error": { "code": ApiErrorCode::InternalError.to_string(), "message": message }
})),
)
}
/// Create a 500 Internal Server Error for database errors with JSON body
pub fn db_error<E: std::fmt::Display>(e: E) -> Custom<Json<Value>> {
internal_error(&format!("Database error: {e}"))
}
/// Create a 503 Service Unavailable error with JSON body
pub fn service_unavailable(code: ApiErrorCode, message: &str) -> Custom<Json<Value>> {
Custom(
Status::ServiceUnavailable,
Json(json!({
"error": { "code": code.to_string(), "message": message }
})),
)
}
// Legacy helper for backward compatibility during migration
2025-02-14 20:43:51 +01:00
pub fn to_internal_error<E: std::fmt::Display>(e: E) -> Custom<String> {
2025-07-16 09:31:14 +02:00
Custom(Status::InternalServerError, format!("Error: {e}"))
2025-02-14 20:43:51 +01:00
}