Skip to main content

breez_sdk_spark/common/
rest.rs

1use std::{collections::HashMap, sync::Arc};
2
3use crate::ServiceConnectivityError;
4
5/// REST client trait for making HTTP requests.
6///
7/// This trait provides a way for users to supply their own HTTP client implementation
8/// for use with the SDK. The SDK will use this client for all HTTP operations including
9/// LNURL flows and chain service requests.
10#[cfg_attr(feature = "uniffi", uniffi::export(with_foreign))]
11#[macros::async_trait]
12pub trait RestClient: Send + Sync {
13    /// Makes a GET request and logs on DEBUG.
14    /// ### Arguments
15    /// - `url`: the URL on which GET will be called
16    /// - `headers`: optional headers that will be set on the request
17    async fn get_request(
18        &self,
19        url: String,
20        headers: Option<HashMap<String, String>>,
21    ) -> Result<RestResponse, ServiceConnectivityError>;
22
23    /// Makes a POST request, and logs on DEBUG.
24    /// ### Arguments
25    /// - `url`: the URL on which POST will be called
26    /// - `headers`: the optional POST headers
27    /// - `body`: the optional POST body
28    async fn post_request(
29        &self,
30        url: String,
31        headers: Option<HashMap<String, String>>,
32        body: Option<String>,
33    ) -> Result<RestResponse, ServiceConnectivityError>;
34
35    /// Makes a DELETE request, and logs on DEBUG.
36    /// ### Arguments
37    /// - `url`: the URL on which DELETE will be called
38    /// - `headers`: the optional DELETE headers
39    /// - `body`: the optional DELETE body
40    async fn delete_request(
41        &self,
42        url: String,
43        headers: Option<HashMap<String, String>>,
44        body: Option<String>,
45    ) -> Result<RestResponse, ServiceConnectivityError>;
46}
47
48#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
49pub struct RestResponse {
50    pub status: u16,
51    pub body: String,
52}
53
54// Conversions are manual (not derived): `platform_utils::HttpResponse` carries
55// response headers that the integrator-facing `RestResponse` does not, so the
56// header map is empty when adapting an external `RestClient` response and
57// dropped in the reverse direction.
58impl From<RestResponse> for platform_utils::HttpResponse {
59    fn from(response: RestResponse) -> Self {
60        platform_utils::HttpResponse {
61            status: response.status,
62            body: response.body,
63            headers: HashMap::new(),
64        }
65    }
66}
67
68impl From<platform_utils::HttpResponse> for RestResponse {
69    fn from(response: platform_utils::HttpResponse) -> Self {
70        RestResponse {
71            status: response.status,
72            body: response.body,
73        }
74    }
75}
76
77/// Wrapper that adapts an external `RestClient` to `platform_utils::HttpClient`
78pub(crate) struct RestClientWrapper {
79    inner: Arc<dyn RestClient>,
80}
81
82impl RestClientWrapper {
83    pub fn new(inner: Arc<dyn RestClient>) -> Self {
84        RestClientWrapper { inner }
85    }
86}
87
88#[macros::async_trait]
89impl platform_utils::HttpClient for RestClientWrapper {
90    async fn get(
91        &self,
92        url: String,
93        headers: Option<HashMap<String, String>>,
94    ) -> Result<platform_utils::HttpResponse, platform_utils::HttpError> {
95        Ok(self.inner.get_request(url, headers).await?.into())
96    }
97
98    async fn post(
99        &self,
100        url: String,
101        headers: Option<HashMap<String, String>>,
102        body: Option<String>,
103    ) -> Result<platform_utils::HttpResponse, platform_utils::HttpError> {
104        Ok(self.inner.post_request(url, headers, body).await?.into())
105    }
106
107    async fn delete(
108        &self,
109        url: String,
110        headers: Option<HashMap<String, String>>,
111        body: Option<String>,
112    ) -> Result<platform_utils::HttpResponse, platform_utils::HttpError> {
113        Ok(self.inner.delete_request(url, headers, body).await?.into())
114    }
115}