Skip to main content

longbridge_httpcli/
client.rs

1use std::sync::Arc;
2
3use reqwest::{
4    Client, Method,
5    header::{HeaderMap, HeaderName, HeaderValue},
6};
7use serde::Deserialize;
8
9use crate::{HttpClientConfig, HttpClientError, HttpClientResult, Json, RequestBuilder};
10
11/// Longbridge HTTP client
12pub struct HttpClient {
13    pub(crate) http_cli: Client,
14    pub(crate) config: Arc<HttpClientConfig>,
15    pub(crate) default_headers: HeaderMap,
16}
17
18impl HttpClient {
19    /// Create a new `HttpClient`
20    pub fn new(config: HttpClientConfig) -> Self {
21        Self {
22            http_cli: Client::new(),
23            config: Arc::new(config),
24            default_headers: HeaderMap::new(),
25        }
26    }
27
28    /// Set the default header
29    pub fn header<K, V>(mut self, key: K, value: V) -> Self
30    where
31        K: TryInto<HeaderName>,
32        V: TryInto<HeaderValue>,
33    {
34        let key = key.try_into();
35        let value = value.try_into();
36        if let (Ok(key), Ok(value)) = (key, value) {
37            self.default_headers.insert(key, value);
38        }
39        self
40    }
41
42    /// Create a new request builder
43    #[inline]
44    pub fn request(
45        &self,
46        method: Method,
47        path: impl Into<String>,
48    ) -> RequestBuilder<'_, (), (), ()> {
49        RequestBuilder::new(self, method, path)
50    }
51
52    /// Get the socket OTP(One Time Password)
53    ///
54    /// Reference: <https://open.longbridge.com/en/docs/socket-token-api>
55    pub async fn get_otp(&self) -> HttpClientResult<String> {
56        #[derive(Debug, Deserialize)]
57        struct Response {
58            otp: String,
59            limit: i32,
60            online: i32,
61        }
62
63        let resp = self
64            .request(Method::GET, "/v1/socket/token")
65            .response::<Json<Response>>()
66            .send()
67            .await?
68            .0;
69        tracing::info!(limit = resp.limit, online = resp.online, "create otp");
70
71        if resp.online >= resp.limit {
72            return Err(HttpClientError::ConnectionLimitExceeded {
73                limit: resp.limit,
74                online: resp.online,
75            });
76        }
77
78        Ok(resp.otp)
79    }
80}