fedimint_connectors/
http.rs1use std::sync::Arc;
2
3use anyhow::anyhow;
4use fedimint_core::util::SafeUrl;
5use fedimint_core::{apply, async_trait_maybe_send};
6use reqwest::{Method, StatusCode};
7use serde_json::Value;
8
9use crate::error::ServerError;
10use crate::{
11 Connectivity, DynGatewayConnection, DynGuaridianConnection, IConnection, IGatewayConnection,
12 ServerResult,
13};
14
15#[derive(Clone, Debug, Default)]
16pub(crate) struct HttpConnector {
17 client: Arc<reqwest::Client>,
18}
19
20#[async_trait::async_trait]
21impl crate::Connector for HttpConnector {
22 async fn connect_guardian(
23 &self,
24 _url: &SafeUrl,
25 _api_secret: Option<&str>,
26 ) -> ServerResult<DynGuaridianConnection> {
27 Err(ServerError::InternalClientError(anyhow!(
28 "Unsupported transport mechanism"
29 )))
30 }
31
32 async fn connect_gateway(&self, url: &SafeUrl) -> anyhow::Result<DynGatewayConnection> {
33 let http_connection = HttpConnection {
34 client: self.client.clone(),
35 base_url: url.clone(),
36 };
37
38 Ok(IGatewayConnection::into_dyn(http_connection))
39 }
40
41 fn connectivity(&self, _url: &SafeUrl) -> Connectivity {
42 Connectivity::Direct
43 }
44}
45
46#[derive(Debug)]
47pub(crate) struct HttpConnection {
48 client: Arc<reqwest::Client>,
49 base_url: SafeUrl,
50}
51
52#[apply(async_trait_maybe_send!)]
53impl IConnection for HttpConnection {
54 async fn await_disconnection(&self) {
55 std::future::pending().await
60 }
61
62 fn is_connected(&self) -> bool {
63 true
69 }
70}
71
72#[apply(async_trait_maybe_send!)]
73impl IGatewayConnection for HttpConnection {
74 async fn request(
75 &self,
76 password: Option<String>,
77 method: Method,
78 route: &str,
79 payload: Option<Value>,
80 ) -> ServerResult<Value> {
81 let url = self.base_url.join(route).expect("Invalid base url");
82 let mut builder = self.client.request(method, url.clone().to_unsafe());
83 if let Some(password) = password.clone() {
84 builder = builder.bearer_auth(password);
85 }
86 if let Some(payload) = payload {
87 builder = builder.json(&payload);
88 }
89
90 let response = builder
91 .send()
92 .await
93 .map_err(|e| ServerError::ServerError(e.into()))?;
94
95 match response.status() {
96 StatusCode::OK => Ok(response
97 .json::<Value>()
98 .await
99 .map_err(|e| ServerError::InvalidResponse(e.into()))?),
100 status => Err(ServerError::InvalidRequest(anyhow::anyhow!(
101 "HTTP request returned unexpected status: {status}"
102 ))),
103 }
104 }
105}