mas_matrix_synapse/
error.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// 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,
                })
            }
        }
    }
}