From e5c7119516db04fcad6440892fcf0b1c1bbf5715 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20K=C3=B6sters?= <timo@koesters.xyz>
Date: Sun, 23 May 2021 16:45:32 +0200
Subject: [PATCH] feat: forward federation errors to the client

---
 src/error.rs         | 21 +++++++++++++++++----
 src/server_server.rs | 25 +++++++++++++++++--------
 2 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/src/error.rs b/src/error.rs
index 6c37bede..e2664e21 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,5 +1,11 @@
 use log::{error, warn};
-use ruma::api::client::{error::ErrorKind, r0::uiaa::UiaaInfo};
+use ruma::{
+    api::client::{
+        error::{Error as RumaError, ErrorKind},
+        r0::uiaa::UiaaInfo,
+    },
+    ServerName,
+};
 use thiserror::Error;
 
 #[cfg(feature = "conduit_bin")]
@@ -10,7 +16,7 @@ use {
         response::{self, Responder},
         Request,
     },
-    ruma::api::client::{error::Error as RumaError, r0::uiaa::UiaaResponse},
+    ruma::api::client::r0::uiaa::UiaaResponse,
 };
 
 pub type Result<T> = std::result::Result<T, Error>;
@@ -33,6 +39,8 @@ pub enum Error {
         source: reqwest::Error,
     },
     #[error("{0}")]
+    FederationError(Box<ServerName>, RumaError),
+    #[error("{0}")]
     BadServerResponse(&'static str),
     #[error("{0}")]
     BadConfig(&'static str),
@@ -66,8 +74,13 @@ where
     'o: 'r,
 {
     fn respond_to(self, r: &'r Request<'_>) -> response::Result<'o> {
-        if let Self::Uiaa(uiaainfo) = &self {
-            return RumaResponse::from(UiaaResponse::AuthResponse(uiaainfo.clone())).respond_to(r);
+        if let Self::Uiaa(uiaainfo) = self {
+            return RumaResponse::from(UiaaResponse::AuthResponse(uiaainfo)).respond_to(r);
+        }
+
+        if let Self::FederationError(origin, mut error) = self {
+            error.message = format!("Answer from {}: {}", origin, error.message);
+            return RumaResponse::from(error).respond_to(r);
         }
 
         let message = format!("{}", self);
diff --git a/src/server_server.rs b/src/server_server.rs
index 699cbbec..82e51fcc 100644
--- a/src/server_server.rs
+++ b/src/server_server.rs
@@ -9,7 +9,7 @@ use regex::Regex;
 use rocket::{response::content::Json, State};
 use ruma::{
     api::{
-        client::error::ErrorKind,
+        client::error::{Error as RumaError, ErrorKind},
         federation::{
             device::get_devices::{self, v1::UserDevice},
             directory::{get_public_rooms, get_public_rooms_filtered},
@@ -27,7 +27,7 @@ use ruma::{
             query::{get_profile_information, get_room_information},
             transactions::{edu::Edu, send_transaction_message},
         },
-        IncomingResponse, OutgoingRequest, OutgoingResponse, SendAccessToken,
+        EndpointError, IncomingResponse, OutgoingRequest, OutgoingResponse, SendAccessToken,
     },
     directory::{IncomingFilter, IncomingRoomNetwork},
     events::{
@@ -261,12 +261,21 @@ where
                 );
             }
 
-            let response = T::IncomingResponse::try_from_http_response(
-                http_response_builder
-                    .body(body)
-                    .expect("reqwest body is valid http body"),
-            );
-            response.map_err(|_| Error::BadServerResponse("Server returned bad response."))
+            let http_response = http_response_builder
+                .body(body)
+                .expect("reqwest body is valid http body");
+
+            if status == 200 {
+                let response = T::IncomingResponse::try_from_http_response(http_response);
+                response.map_err(|_| Error::BadServerResponse("Server returned bad 200 response."))
+            } else {
+                Err(Error::FederationError(
+                    destination.to_owned(),
+                    RumaError::try_from_http_response(http_response).map_err(|_| {
+                        Error::BadServerResponse("Server returned bad error response.")
+                    })?,
+                ))
+            }
         }
         Err(e) => Err(e.into()),
     }