Files
letro-authentication-service/crates/matrix-synapse/src/error.rs
2024-10-28 13:46:38 +01:00

70 lines
1.8 KiB
Rust

// Copyright 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
use std::fmt::Display;
use async_trait::async_trait;
use serde::Deserialize;
use thiserror::Error;
/// Represents a Matrix error
/// Ref: <https://spec.matrix.org/v1.10/client-server-api/#standard-error-response>
#[derive(Debug, Deserialize)]
struct MatrixError {
errcode: String,
error: String,
}
/// Represents an error received from the homeserver.
/// Where possible, we capture the Matrix error from the JSON response body.
#[derive(Debug, Error)]
pub(crate) struct Error {
synapse_error: Option<MatrixError>,
#[source]
source: reqwest::Error,
}
impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(matrix_error) = &self.synapse_error {
write!(f, "{}: {}", matrix_error.errcode, matrix_error.error)
} else {
write!(f, "(no specific error)")
}
}
}
impl Error {
/// Return the error code (`errcode`)
pub fn errcode(&self) -> Option<&str> {
let me = self.synapse_error.as_ref()?;
Some(&me.errcode)
}
}
/// An extension trait for [`reqwest::Response`] to help working with errors
/// from Synapse.
#[async_trait]
pub(crate) trait SynapseResponseExt: Sized {
async fn error_for_synapse_error(self) -> Result<Self, Error>;
}
#[async_trait]
impl SynapseResponseExt for reqwest::Response {
async fn error_for_synapse_error(self) -> Result<Self, Error> {
match self.error_for_status_ref() {
Ok(_response) => Ok(self),
Err(source) => {
let synapse_error = self.json().await.ok();
Err(Error {
synapse_error,
source,
})
}
}
}
}