blob: 2a6bdc4b4bc44b2ee69d2d0d1870c8e84072b196 [file] [log] [blame]
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use axum::Json;
use iggy::error::IggyError;
use serde::Serialize;
use thiserror::Error;
use tracing::error;
#[derive(Debug, Error)]
pub enum CustomError {
#[error(transparent)]
Error(#[from] IggyError),
#[error("Resource not found")]
ResourceNotFound,
}
#[derive(Debug, Serialize)]
pub struct ErrorResponse {
pub id: u32,
pub code: String,
pub reason: String,
pub field: Option<String>,
}
impl IntoResponse for CustomError {
fn into_response(self) -> Response {
match self {
CustomError::Error(error) => {
error!("There was an error: {error}");
let status_code = match error {
IggyError::StreamIdNotFound(_) => StatusCode::NOT_FOUND,
IggyError::TopicIdNotFound(_, _) => StatusCode::NOT_FOUND,
IggyError::PartitionNotFound(_, _, _) => StatusCode::NOT_FOUND,
IggyError::SegmentNotFound => StatusCode::NOT_FOUND,
IggyError::ClientNotFound(_) => StatusCode::NOT_FOUND,
IggyError::ConsumerGroupIdNotFound(_, _) => StatusCode::NOT_FOUND,
IggyError::ConsumerGroupNameNotFound(_, _) => StatusCode::NOT_FOUND,
IggyError::ConsumerGroupMemberNotFound(_, _, _) => StatusCode::NOT_FOUND,
IggyError::ConsumerOffsetNotFound(_) => StatusCode::NOT_FOUND,
IggyError::ResourceNotFound(_) => StatusCode::NOT_FOUND,
IggyError::Unauthenticated => StatusCode::UNAUTHORIZED,
IggyError::AccessTokenMissing => StatusCode::UNAUTHORIZED,
IggyError::InvalidAccessToken => StatusCode::UNAUTHORIZED,
IggyError::InvalidPersonalAccessToken => StatusCode::UNAUTHORIZED,
IggyError::Unauthorized => StatusCode::FORBIDDEN,
_ => StatusCode::BAD_REQUEST,
};
(status_code, Json(ErrorResponse::from_error(error)))
}
CustomError::ResourceNotFound => (
StatusCode::NOT_FOUND,
Json(ErrorResponse {
id: 404,
code: "not_found".to_string(),
reason: "Resource not found".to_string(),
field: None,
}),
),
}
.into_response()
}
}
impl ErrorResponse {
pub fn from_error(error: IggyError) -> Self {
ErrorResponse {
id: error.as_code(),
code: error.as_string().to_string(),
reason: error.to_string(),
field: match error {
IggyError::StreamIdNotFound(_) => Some("stream_id".to_string()),
IggyError::TopicIdNotFound(_, _) => Some("topic_id".to_string()),
IggyError::PartitionNotFound(_, _, _) => Some("partition_id".to_string()),
IggyError::SegmentNotFound => Some("segment_id".to_string()),
IggyError::ClientNotFound(_) => Some("client_id".to_string()),
IggyError::InvalidStreamName => Some("name".to_string()),
IggyError::StreamNameAlreadyExists(_) => Some("name".to_string()),
IggyError::InvalidTopicName => Some("name".to_string()),
IggyError::TopicNameAlreadyExists(_, _) => Some("name".to_string()),
IggyError::InvalidStreamId => Some("stream_id".to_string()),
IggyError::StreamIdAlreadyExists(_) => Some("stream_id".to_string()),
IggyError::InvalidTopicId => Some("topic_id".to_string()),
IggyError::TopicIdAlreadyExists(_, _) => Some("topic_id".to_string()),
IggyError::InvalidOffset(_) => Some("offset".to_string()),
IggyError::InvalidConsumerGroupId => Some("consumer_group_id".to_string()),
IggyError::ConsumerGroupIdAlreadyExists(_, _) => {
Some("consumer_group_id".to_string())
}
IggyError::ConsumerGroupNameAlreadyExists(_, _) => Some("name".to_string()),
IggyError::UserAlreadyExists => Some("username".to_string()),
IggyError::PersonalAccessTokenAlreadyExists(_, _) => Some("name".to_string()),
_ => None,
},
}
}
}