longport_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/// LongPort 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    /// Create a new `HttpClient` from the given environment variables
29    ///
30    /// # Variables
31    ///
32    /// - LONGPORT_APP_KEY
33    /// - LONGPORT_APP_SECRET
34    /// - LONGPORT_ACCESS_TOKEN
35    /// - LONGPORT_HTTP_URL
36    pub fn from_env() -> Result<Self, HttpClientError> {
37        Ok(Self::new(HttpClientConfig::from_env()?))
38    }
39
40    /// Set the default header
41    pub fn header<K, V>(mut self, key: K, value: V) -> Self
42    where
43        K: TryInto<HeaderName>,
44        V: TryInto<HeaderValue>,
45    {
46        let key = key.try_into();
47        let value = value.try_into();
48        if let (Ok(key), Ok(value)) = (key, value) {
49            self.default_headers.insert(key, value);
50        }
51        self
52    }
53
54    /// Create a new request builder
55    #[inline]
56    pub fn request(
57        &self,
58        method: Method,
59        path: impl Into<String>,
60    ) -> RequestBuilder<'_, (), (), ()> {
61        RequestBuilder::new(self, method, path)
62    }
63
64    /// Get the socket OTP(One Time Password)
65    ///
66    /// Reference: <https://open.longportapp.com/en/docs/socket-token-api>
67    pub async fn get_otp(&self) -> HttpClientResult<String> {
68        #[derive(Debug, Deserialize)]
69        struct Response {
70            otp: String,
71        }
72
73        Ok(self
74            .request(Method::GET, "/v1/socket/token")
75            .response::<Json<Response>>()
76            .send()
77            .await?
78            .0
79            .otp)
80    }
81
82    /// Get the socket OTP v2(One Time Password)
83    ///
84    /// Reference: <https://open.longportapp.com/en/docs/socket-token-api>
85    pub async fn get_otp_v2(&self) -> HttpClientResult<String> {
86        #[derive(Debug, Deserialize)]
87        struct Response {
88            otp: String,
89        }
90
91        Ok(self
92            .request(Method::GET, "/v2/socket/token")
93            .response::<Json<Response>>()
94            .send()
95            .await?
96            .0
97            .otp)
98    }
99}