JSON error (playing with serde API)

This commit is contained in:
Igor Katson 2022-12-08 20:13:01 +00:00
parent 8b621059c1
commit 871d927596
No known key found for this signature in database
GPG key ID: B4EC22B66D61A3F5

View file

@ -1,7 +1,10 @@
use std::ops::Deref;
use axum::{
http::StatusCode,
response::{IntoResponse, Response},
};
use serde::{ser::SerializeMap, Serialize, Serializer};
// Convenience error type.
#[derive(Debug)]
@ -38,6 +41,53 @@ enum ApiErrorKind {
Other(anyhow::Error),
}
struct ErrWrap<'a, E: ?Sized>(&'a E);
impl<'a, E> Serialize for ErrWrap<'a, E>
where
E: std::error::Error + ?Sized,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut m = serializer.serialize_map(None)?;
m.serialize_entry("description", &format!("{}", self.0))?;
if let Some(source) = self.0.source() {
m.serialize_entry("source", &ErrWrap(source))?;
}
m.end()
}
}
impl Serialize for ApiErrorKind {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
ApiErrorKind::TorrentNotFound(id) => {
let mut m = serializer.serialize_map(None)?;
m.serialize_entry("error_kind", "torrent_not_found")?;
m.serialize_entry("id", id)?;
m.end()
}
ApiErrorKind::DhtDisabled => {
let mut m = serializer.serialize_map(None)?;
m.serialize_entry("error_kind", "dht_disabled")?;
m.end()
}
ApiErrorKind::Other(err) => {
let mut m = serializer.serialize_map(None)?;
m.serialize_entry("error_kind", "internal_error")?;
m.serialize_entry("human_readable", &format!("{err:#}"))?;
m.serialize_entry("error_chain", &ErrWrap(err.deref()))?;
m.end()
}
}
}
}
impl From<anyhow::Error> for ApiError {
fn from(value: anyhow::Error) -> Self {
Self {
@ -68,7 +118,7 @@ impl std::fmt::Display for ApiError {
impl IntoResponse for ApiError {
fn into_response(self) -> Response {
let mut response = format!("{self}").into_response();
let mut response = axum::Json(&self.kind).into_response();
*response.status_mut() = match self.status {
Some(s) => s,
None => StatusCode::INTERNAL_SERVER_ERROR,