1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-11-20 12:02:22 +03:00
Files
authentication-service/crates/matrix-synapse/src/error.rs
reivilibre 49e8fe57f4 Improve errors when MAS contacts the Synapse homeserver (#2794)
* Add some drive-by docstrings

* Change text rendering of catch_http_codes::HttpError

Using `#[source]` is unnatural here because it makes it look like
two distinct errors (one being a cause of the other),
when in reality it is just one error, with 2 parts.

Using `Display` formatting for that leads to a more natural error.

* Add constraints to `catch_http_code{,s}` methods

Not strictly required, but does two things:

- documents what kind of function is expected
- provides a small extra amount of type enforcement at the call site,
  rather than later on when you find the result doesn't implement Service

* Add a `catch_http_errors` shorthand

Nothing major, just a quality of life improvement so you don't have to
repetitively write out what a HTTP error is

* Unexpected error page: remove leading whitespace from preformatted 'details' section

The extra whitespace was probably unintentional and makes the error harder to read,
particularly when it wraps onto a new line unnecessarily

* Capture and log Matrix errors received from Synapse

* Drive-by clippy fix: use clamp instead of min().max()

* Convert `err(Display)` to `err(Debug)` for `anyhow::Error`s in matrix-synapse support module
2024-06-07 11:14:04 +00:00

65 lines
2.0 KiB
Rust

use std::{error::Error, fmt::Display};
use http::Response;
use mas_axum_utils::axum::body::Bytes;
use serde::Deserialize;
use tracing::debug;
/// 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.
///
/// Note that the `CatchHttpCodes` layer already captures the `StatusCode` for
/// us; we don't need to do that twice.
#[derive(Debug)]
pub(crate) struct HomeserverError {
matrix_error: Option<MatrixError>,
}
impl Display for HomeserverError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(matrix_error) = &self.matrix_error {
write!(f, "{matrix_error}")
} else {
write!(f, "(no specific error)")
}
}
}
impl Error for HomeserverError {}
impl HomeserverError {
/// Return the error code (`errcode`)
pub fn errcode(&self) -> Option<&str> {
self.matrix_error.as_ref().map(|me| me.errcode.as_str())
}
}
/// Parses a JSON-encoded Matrix error from the response body
/// Spec reference: <https://spec.matrix.org/v1.10/client-server-api/#standard-error-response>
#[allow(clippy::needless_pass_by_value)]
pub(crate) fn catch_homeserver_error(response: Response<Bytes>) -> HomeserverError {
let matrix_error: Option<MatrixError> = match serde_json::from_slice(response.body().as_ref()) {
Ok(body) => Some(body),
Err(err) => {
debug!("failed to deserialise expected homeserver error: {err:?}");
None
}
};
HomeserverError { matrix_error }
}
impl Display for MatrixError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let MatrixError { errcode, error } = &self;
write!(f, "{errcode}: {error}")
}
}