dex_connector/
dex_request.rs

1use reqwest::{
2    header::{HeaderMap, HeaderValue},
3    Client, Method,
4};
5use serde::Serialize;
6use std::{
7    collections::HashMap,
8    error::Error as StdError,
9    fmt::{self, Display},
10};
11
12pub enum HttpMethod {
13    Get,
14    Post,
15    Put,
16    Delete,
17}
18
19impl From<HttpMethod> for Method {
20    fn from(method: HttpMethod) -> Self {
21        match method {
22            HttpMethod::Get => Method::GET,
23            HttpMethod::Post => Method::POST,
24            HttpMethod::Put => Method::PUT,
25            HttpMethod::Delete => Method::DELETE,
26        }
27    }
28}
29
30#[derive(Clone, Debug)]
31pub struct DexRequest {
32    client: Client,
33    endpoint: String,
34}
35
36#[derive(Debug)]
37pub enum DexError {
38    Serde(serde_json::Error),
39    Reqwest(reqwest::Error),
40    ServerResponse(String),
41    WebSocketError(String),
42    Other(String),
43    NoConnection,
44}
45
46impl Display for DexError {
47    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48        match *self {
49            DexError::Serde(ref e) => write!(f, "Serde JSON error: {}", e),
50            DexError::Reqwest(ref e) => write!(f, "Reqwest error: {}", e),
51            DexError::ServerResponse(ref e) => write!(f, "Server response error: {}", e),
52            DexError::Other(ref e) => write!(f, "Other error: {}", e),
53            DexError::NoConnection => write!(f, "No running WebSocketConnection"),
54            DexError::WebSocketError(ref e) => write!(f, "WebSocket error: {}", e),
55        }
56    }
57}
58
59impl StdError for DexError {
60    fn source(&self) -> Option<&(dyn StdError + 'static)> {
61        match *self {
62            DexError::Serde(ref e) => Some(e),
63            DexError::Reqwest(ref e) => Some(e),
64            DexError::ServerResponse(_) => None,
65            DexError::Other(_) => None,
66            DexError::NoConnection => None,
67            DexError::WebSocketError(_) => None,
68        }
69    }
70}
71
72impl From<reqwest::Error> for DexError {
73    fn from(error: reqwest::Error) -> Self {
74        DexError::Reqwest(error)
75    }
76}
77
78impl DexRequest {
79    pub async fn new(endpoint: String) -> Result<Self, DexError> {
80        let client = Client::builder().cookie_store(true).build()?;
81
82        Ok(DexRequest { client, endpoint })
83    }
84
85    pub async fn handle_request<T: serde::de::DeserializeOwned, U: Serialize + ?Sized>(
86        &self,
87        method: HttpMethod,
88        request_url: String,
89        headers: &HashMap<String, String>,
90        json_payload: String,
91    ) -> Result<T, DexError> {
92        let url = format!("{}{}", self.endpoint, request_url);
93
94        let mut header_map = HeaderMap::new();
95        header_map.insert(
96            reqwest::header::CONTENT_TYPE,
97            HeaderValue::from_static("application/json"),
98        );
99
100        for (key, value) in headers.iter() {
101            let key = reqwest::header::HeaderName::from_bytes(key.as_bytes())
102                .expect("Failed to create HeaderName");
103            let value = HeaderValue::from_str(value).expect("Failed to create HeaderValue");
104            header_map.insert(key, value);
105        }
106
107        let client = self.client.clone();
108        let request_builder = client
109            .request(Method::from(method), &url)
110            .headers(header_map);
111
112        log::trace!("payload = {}", json_payload);
113
114        let request_builder = if !json_payload.is_empty() {
115            request_builder.body(json_payload.clone())
116        } else {
117            request_builder
118        };
119
120        let response = request_builder.send().await.map_err(DexError::from)?;
121        let status = response.status();
122
123        if !status.is_success() {
124            let error_message =
125                format!("Server returned error: {}. requested url: {}", status, url);
126            log::error!("{}", &error_message);
127        }
128
129        let response_headers = response.headers().clone();
130        log::trace!("Response header: {:?}", response_headers);
131
132        let response_body = response.text().await.map_err(DexError::from)?;
133        log::trace!("Response body: {}", response_body);
134
135        serde_json::from_str(&response_body).map_err(|e| {
136            log::error!(
137                "Failed to deserialize response: {}, payload = {}",
138                e,
139                json_payload
140            );
141            DexError::Serde(e)
142        })
143    }
144}