Skip to main content

srs_client/
http_api.rs

1//! [HTTP API] definitions of [SRS].
2//!
3//! [SRS]: https://ossrs.io/
4//! [1]: https://ossrs.io/lts/en-us/docs/v5/doc/http-api
5#![allow(unused_imports)]
6
7mod client;
8mod common;
9mod error;
10mod feature;
11mod meminfos;
12mod response;
13mod rusages;
14mod self_proc_stats;
15mod stream;
16mod summary;
17mod system_proc_stats;
18mod vhost;
19
20pub use error::SrsClientError;
21pub use response::{SrsClientResp, SrsClientRespData};
22pub use stream::Stream;
23
24use reqwest::{Client, Response as ReqwestResponse};
25use url::Url;
26
27/// Client for performing requests to [HTTP API][1] of spawned [SRS].
28///
29/// [SRS]: https://ossrs.io/
30/// [1]: https://ossrs.io/lts/en-us/docs/v5/doc/http-api
31#[derive(Clone, Debug)]
32pub struct SrsClient {
33    http_client: Client,
34    base_url: Url,
35}
36
37impl SrsClient {
38    /// Build [`SrsClient`] for future call to [HTTP API][1] API of spawned [SRS]. .
39    ///
40    /// # Errors
41    ///
42    /// If incorrect `base_url` passed
43    ///
44    /// [SRS]: https://ossrs.io/
45    /// [1]: https://ossrs.io/lts/en-us/docs/v5/doc/http-api
46    pub fn build<S: Into<String>>(base_url: S) -> Result<Self, SrsClientError> {
47        let base_url = Url::parse(&base_url.into())
48            .and_then(|url| url.join("/api/v1/"))
49            .map_err(SrsClientError::IncorrectBaseUrl)?;
50        tracing::debug!("base_url: {base_url}");
51        Ok(Self {
52            http_client: Client::new(),
53            base_url,
54        })
55    }
56
57    async fn get(&self, url: &str) -> Result<ReqwestResponse, SrsClientError> {
58        self.http_client
59            .get(
60                self.base_url
61                    .join(url)
62                    .map_err(SrsClientError::IncorrectApiUrl)?,
63            )
64            .send()
65            .await
66            .map_err(SrsClientError::RequestFailed)
67    }
68
69    async fn delete(&self, url: &str) -> Result<ReqwestResponse, SrsClientError> {
70        self.http_client
71            .delete(
72                self.base_url
73                    .join(url)
74                    .map_err(SrsClientError::IncorrectApiUrl)?,
75            )
76            .send()
77            .await
78            .map_err(SrsClientError::RequestFailed)
79    }
80
81    async fn process_resp(&self, resp: ReqwestResponse) -> Result<SrsClientResp, SrsClientError> {
82        if !resp.status().is_success() {
83            return Err(SrsClientError::BadStatus(resp.status()));
84        }
85        // tracing::debug!(url = resp.url().to_string(), "processing request");
86        tracing::debug!("processing request to: {}", resp.url());
87        let resp = resp
88            .json::<SrsClientResp>()
89            .await
90            .map_err(SrsClientError::DeserializeError)?;
91        Ok(resp)
92    }
93
94    /// [Kicks off][1] a client connected to [SRS] server by its `id`.
95    ///
96    /// # Errors
97    ///
98    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
99    /// for details.
100    ///
101    /// [SRS]: https://ossrs.io/
102    /// [1]: https://ossrs.io/lts/en-us/docs/v5/doc/http-api#kickoff-client
103    pub async fn kickoff_client<T: Into<String>>(
104        self,
105        id: T,
106    ) -> Result<SrsClientResp, SrsClientError> {
107        let resp = self.delete(&format!("clients/{}/", id.into())).await?;
108        self.process_resp(resp).await
109    }
110
111    /// Retrieves the server version.
112    ///
113    /// # Errors
114    ///
115    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
116    /// for details.
117    pub async fn get_version(self) -> Result<SrsClientResp, SrsClientError> {
118        let resp = self.get("versions").await?;
119        self.process_resp(resp).await
120    }
121
122    /// Manages all vhosts or a specified vhost.
123    ///
124    /// # Errors
125    ///
126    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
127    /// for details.
128    pub async fn get_vhosts(self) -> Result<SrsClientResp, SrsClientError> {
129        let resp = self.get("vhosts").await?;
130        self.process_resp(resp).await
131    }
132
133    /// Manages all streams or a specified stream.
134    ///
135    /// # Errors
136    ///
137    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
138    /// for details.
139    pub async fn get_streams(self) -> Result<SrsClientResp, SrsClientError> {
140        let resp = self.get("streams").await?;
141        self.process_resp(resp).await
142    }
143
144    /// Retrieves all streams as a typed list.
145    ///
146    /// # Errors
147    ///
148    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
149    /// for details.
150    pub async fn get_stream_list(self) -> Result<Vec<Stream>, SrsClientError> {
151        let response = self.get_streams().await?;
152        match response.data {
153            SrsClientRespData::Streams { streams } => Ok(streams),
154            _ => Ok(Vec::new()),
155        }
156    }
157
158    /// Manages all clients or a specified client, default query top 10 clients.
159    ///
160    /// # Errors
161    ///
162    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
163    /// for details.
164    pub async fn get_clients(self) -> Result<SrsClientResp, SrsClientError> {
165        let resp = self.get("clients").await?;
166        self.process_resp(resp).await
167    }
168
169    /// Retrieves the supported features of SRS.
170    ///
171    /// # Errors
172    ///
173    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
174    /// for details.
175    pub async fn get_features(self) -> Result<SrsClientResp, SrsClientError> {
176        let resp = self.get("features").await?;
177        self.process_resp(resp).await
178    }
179
180    /// Retrieves the rusage of SRS.
181    ///
182    /// # Errors
183    ///
184    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
185    /// for details.
186    pub async fn get_rusages(self) -> Result<SrsClientResp, SrsClientError> {
187        let resp = self.get("rusages").await?;
188        self.process_resp(resp).await
189    }
190
191    /// Retrieves the self process stats.
192    ///
193    /// # Errors
194    ///
195    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
196    /// for details.
197    pub async fn get_self_proc_stats(self) -> Result<SrsClientResp, SrsClientError> {
198        let resp = self.get("self_proc_stats").await?;
199        self.process_resp(resp).await
200    }
201
202    /// Retrieves the system process stats.
203    ///
204    /// # Errors
205    ///
206    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
207    /// for details.
208    pub async fn get_system_proc_stats(self) -> Result<SrsClientResp, SrsClientError> {
209        let resp = self.get("system_proc_stats").await?;
210        self.process_resp(resp).await
211    }
212
213    /// Retrieves the meminfo of system.
214    ///
215    /// # Errors
216    ///
217    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
218    /// for details.
219    pub async fn get_meminfos(self) -> Result<SrsClientResp, SrsClientError> {
220        let resp = self.get("meminfos").await?;
221        self.process_resp(resp).await
222    }
223}