longbridge_httpcli/
client.rs

1use std::sync::Arc;
2
3use reqwest::{
4    header::{HeaderMap, HeaderName, HeaderValue},
5    Client, Method,
6};
7use serde::Deserialize;
8
9use crate::{HttpClientConfig, HttpClientError, HttpClientResult, Json, RequestBuilder};
10
11/// Longbridge HTTP client
12#[derive(Clone)]
13pub struct HttpClient {
14    pub(crate) http_cli: Client,
15    pub(crate) config: Arc<HttpClientConfig>,
16    pub(crate) default_headers: HeaderMap,
17}
18
19impl HttpClient {
20    /// Create a new `HttpClient`
21    pub fn new(config: HttpClientConfig) -> Self {
22        Self {
23            http_cli: Client::new(),
24            config: Arc::new(config),
25            default_headers: HeaderMap::new(),
26        }
27    }
28
29    /// Create a new `HttpClient` from the given environment variables
30    ///
31    /// # Variables
32    ///
33    /// - LONGBRIDGE_APP_KEY
34    /// - LONGBRIDGE_APP_SECRET
35    /// - LONGBRIDGE_ACCESS_TOKEN
36    /// - LONGBRIDGE_HTTP_URL
37    pub fn from_env() -> Result<Self, HttpClientError> {
38        Ok(Self::new(HttpClientConfig::from_env()?))
39    }
40
41    /// Set the default header
42    pub fn header<K, V>(mut self, key: K, value: V) -> Self
43    where
44        K: TryInto<HeaderName>,
45        V: TryInto<HeaderValue>,
46    {
47        let key = key.try_into();
48        let value = value.try_into();
49        if let (Ok(key), Ok(value)) = (key, value) {
50            self.default_headers.append(key, value);
51        }
52        self
53    }
54
55    /// Create a new request builder
56    #[inline]
57    pub fn request(&self, method: Method, path: impl Into<String>) -> RequestBuilder<(), (), ()> {
58        RequestBuilder::new(self.clone(), method, path)
59    }
60
61    /// Get the socket OTP(One Time Password)
62    ///
63    /// Reference: <https://open.longbridgeapp.com/en/docs/socket-token-api>
64    pub async fn get_otp(&self) -> HttpClientResult<String> {
65        #[derive(Debug, Deserialize)]
66        struct Response {
67            otp: String,
68        }
69
70        Ok(self
71            .request(Method::GET, "/v1/socket/token")
72            .response::<Json<Response>>()
73            .send()
74            .await?
75            .0
76            .otp)
77    }
78
79    /// Get the socket OTP v2(One Time Password)
80    ///
81    /// Reference: <https://open.longbridgeapp.com/en/docs/socket-token-api>
82    pub async fn get_otp_v2(&self) -> HttpClientResult<String> {
83        #[derive(Debug, Deserialize)]
84        struct Response {
85            otp: String,
86        }
87
88        Ok(self
89            .request(Method::GET, "/v2/socket/token")
90            .response::<Json<Response>>()
91            .send()
92            .await?
93            .0
94            .otp)
95    }
96}