114 lines
3.0 KiB
Rust
114 lines
3.0 KiB
Rust
use actix_web::{HttpResponse, ResponseError};
|
|
use serde::Serialize;
|
|
use service::error::AppError;
|
|
use utoipa::openapi::schema::{KnownFormat, ObjectBuilder, SchemaFormat, Type};
|
|
use utoipa::openapi::{RefOr, Schema};
|
|
use utoipa::{PartialSchema, ToSchema};
|
|
|
|
#[derive(Debug, Serialize, ToSchema)]
|
|
pub struct ApiResponse<T> {
|
|
pub code: i32,
|
|
pub message: String,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub data: Option<T>,
|
|
}
|
|
|
|
impl<T: Serialize> ApiResponse<T> {
|
|
pub fn ok(data: T) -> Self {
|
|
Self {
|
|
code: 0,
|
|
message: "ok".to_string(),
|
|
data: Some(data),
|
|
}
|
|
}
|
|
|
|
pub fn to_response(self) -> HttpResponse {
|
|
HttpResponse::Ok().json(self)
|
|
}
|
|
}
|
|
|
|
pub fn api_success() -> HttpResponse {
|
|
HttpResponse::Ok().json(ApiResponse {
|
|
code: 0,
|
|
message: "ok".to_string(),
|
|
data: None::<()>,
|
|
})
|
|
}
|
|
|
|
#[derive(Debug, Serialize, ToSchema)]
|
|
pub struct ApiErrorResponse {
|
|
pub code: i32,
|
|
pub error: String,
|
|
pub message: String,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ApiError(pub AppError);
|
|
|
|
impl std::fmt::Display for ApiError {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
self.0.user_message().fmt(f)
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for ApiError {}
|
|
|
|
impl From<AppError> for ApiError {
|
|
fn from(e: AppError) -> Self {
|
|
ApiError(e)
|
|
}
|
|
}
|
|
|
|
impl From<room::RoomError> for ApiError {
|
|
fn from(e: room::RoomError) -> Self {
|
|
ApiError(e.into())
|
|
}
|
|
}
|
|
|
|
impl ResponseError for ApiError {
|
|
fn error_response(&self) -> HttpResponse {
|
|
let err = &self.0;
|
|
let status = actix_web::http::StatusCode::from_u16(err.http_status_code())
|
|
.unwrap_or(actix_web::http::StatusCode::INTERNAL_SERVER_ERROR);
|
|
let resp = ApiErrorResponse {
|
|
code: err.code(),
|
|
error: err.slug().to_string(),
|
|
message: err.user_message(),
|
|
};
|
|
HttpResponse::build(status).json(resp)
|
|
}
|
|
}
|
|
|
|
impl PartialSchema for ApiError {
|
|
fn schema() -> RefOr<Schema> {
|
|
RefOr::T(Schema::Object(
|
|
ObjectBuilder::new()
|
|
.property(
|
|
"code",
|
|
ObjectBuilder::new()
|
|
.schema_type(Type::Integer)
|
|
.format(Some(SchemaFormat::KnownFormat(KnownFormat::Int32)))
|
|
.description(Some("Error numeric code")),
|
|
)
|
|
.property(
|
|
"error",
|
|
ObjectBuilder::new()
|
|
.schema_type(Type::String)
|
|
.description(Some("Error slug identifier")),
|
|
)
|
|
.property(
|
|
"message",
|
|
ObjectBuilder::new()
|
|
.schema_type(Type::String)
|
|
.description(Some("Human-readable error message")),
|
|
)
|
|
.required("code")
|
|
.required("error")
|
|
.required("message")
|
|
.into(),
|
|
))
|
|
}
|
|
}
|
|
|
|
impl ToSchema for ApiError {}
|