use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
pub struct ProblemDetails {
#[serde(rename = "type")]
pub type_uri: String,
pub title: String,
pub status: u16,
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<String>,
#[serde(rename = "instance", skip_serializing_if = "Option::is_none")]
pub instance: Option<String>,
}
impl ProblemDetails {
pub fn new(status: StatusCode, title: impl Into<String>, detail: Option<String>) -> Self {
Self {
type_uri: "about:blank".to_string(),
title: title.into(),
status: status.as_u16(),
detail,
instance: None,
}
}
pub fn with_type_uri(mut self, uri: impl Into<String>) -> Self {
self.type_uri = uri.into();
self
}
pub fn with_instance(mut self, instance: impl Into<String>) -> Self {
self.instance = Some(instance.into());
self
}
}
impl IntoResponse for ProblemDetails {
fn into_response(self) -> Response {
let status = StatusCode::from_u16(self.status).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
(
status,
[(
axum::http::header::CONTENT_TYPE,
axum::http::HeaderValue::from_static("application/problem+json"),
)],
serde_json::to_string(&self).unwrap_or_else(|_| "{}".to_string()),
)
.into_response()
}
}