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 client::Client;
21pub use common::{Hls, Kbps, Publish};
22pub use error::SrsClientError;
23pub use response::{SrsClientResp, SrsClientRespData};
24pub use stream::{Audio, Stream, Video};
25pub use summary::{Summary, Tests, Urls};
26pub use vhost::Vhost;
27
28use reqwest::{Client as ReqwestClient, Response as ReqwestResponse};
29use url::Url;
30
31/// Client for performing requests to [HTTP API][1] of spawned [SRS].
32///
33/// [SRS]: https://ossrs.io/
34/// [1]: https://ossrs.io/lts/en-us/docs/v5/doc/http-api
35#[derive(Clone, Debug)]
36pub struct SrsClient {
37    http_client: ReqwestClient,
38    base_url: Url,
39}
40
41impl SrsClient {
42    /// Build [`SrsClient`] for future call to [HTTP API][1] API of spawned [SRS]. .
43    ///
44    /// # Errors
45    ///
46    /// If incorrect `base_url` passed
47    ///
48    /// [SRS]: https://ossrs.io/
49    /// [1]: https://ossrs.io/lts/en-us/docs/v5/doc/http-api
50    pub fn build<S: Into<String>>(base_url: S) -> Result<Self, SrsClientError> {
51        let base_url = Url::parse(&base_url.into())
52            .and_then(|url| url.join("/api/v1/"))
53            .map_err(SrsClientError::IncorrectBaseUrl)?;
54        tracing::debug!("base_url: {base_url}");
55        Ok(Self {
56            http_client: ReqwestClient::new(),
57            base_url,
58        })
59    }
60
61    async fn get(&self, url: &str) -> Result<ReqwestResponse, SrsClientError> {
62        self.http_client
63            .get(
64                self.base_url
65                    .join(url)
66                    .map_err(SrsClientError::IncorrectApiUrl)?,
67            )
68            .send()
69            .await
70            .map_err(SrsClientError::RequestFailed)
71    }
72
73    async fn delete(&self, url: &str) -> Result<ReqwestResponse, SrsClientError> {
74        self.http_client
75            .delete(
76                self.base_url
77                    .join(url)
78                    .map_err(SrsClientError::IncorrectApiUrl)?,
79            )
80            .send()
81            .await
82            .map_err(SrsClientError::RequestFailed)
83    }
84
85    async fn process_resp(&self, resp: ReqwestResponse) -> Result<SrsClientResp, SrsClientError> {
86        if !resp.status().is_success() {
87            return Err(SrsClientError::BadStatus(resp.status()));
88        }
89        // tracing::debug!(url = resp.url().to_string(), "processing request");
90        tracing::debug!("processing request to: {}", resp.url());
91        let resp = resp
92            .json::<SrsClientResp>()
93            .await
94            .map_err(SrsClientError::DeserializeError)?;
95        Ok(resp)
96    }
97
98    /// [Kicks off][1] a client connected to [SRS] server by its `id`.
99    ///
100    /// # Errors
101    ///
102    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
103    /// for details.
104    ///
105    /// [SRS]: https://ossrs.io/
106    /// [1]: https://ossrs.io/lts/en-us/docs/v5/doc/http-api#kickoff-client
107    pub async fn kickoff_client<T: Into<String>>(
108        self,
109        id: T,
110    ) -> Result<SrsClientResp, SrsClientError> {
111        let resp = self.delete(&format!("clients/{}/", id.into())).await?;
112        self.process_resp(resp).await
113    }
114
115    /// Retrieves the server version.
116    ///
117    /// # Errors
118    ///
119    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
120    /// for details.
121    pub async fn get_version(self) -> Result<SrsClientResp, SrsClientError> {
122        let resp = self.get("versions").await?;
123        self.process_resp(resp).await
124    }
125
126    /// Retrieves the server summary.
127    ///
128    /// # Errors
129    ///
130    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
131    /// for details.
132    pub async fn get_summaries(self) -> Result<SrsClientResp, SrsClientError> {
133        let resp = self.get("summaries").await?;
134        self.process_resp(resp).await
135    }
136
137    /// Retrieves the server summary as typed data.
138    ///
139    /// # Errors
140    ///
141    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
142    /// for details.
143    pub async fn get_summary(self) -> Result<Option<Summary>, SrsClientError> {
144        let response = self.get_summaries().await?;
145        match response.data {
146            SrsClientRespData::Summary(summary) => Ok(Some(summary)),
147            _ => Err(SrsClientError::UnexpectedResponse("summary")),
148        }
149    }
150
151    /// Retrieves the HTTP request debug API description.
152    ///
153    /// # Errors
154    ///
155    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
156    /// for details.
157    pub async fn get_requests(self) -> Result<SrsClientResp, SrsClientError> {
158        let resp = self.get("requests").await?;
159        self.process_resp(resp).await
160    }
161
162    /// Retrieves the HTTP request debug API description as typed summary data.
163    ///
164    /// # Errors
165    ///
166    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
167    /// for details.
168    pub async fn get_requests_summary(self) -> Result<Option<Summary>, SrsClientError> {
169        let response = self.get_requests().await?;
170        match response.data {
171            SrsClientRespData::Summary(summary) => Ok(Some(summary)),
172            _ => Err(SrsClientError::UnexpectedResponse("requests summary")),
173        }
174    }
175
176    /// Retrieves the SRS config API description.
177    ///
178    /// # Errors
179    ///
180    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
181    /// for details.
182    pub async fn get_configs(self) -> Result<SrsClientResp, SrsClientError> {
183        let resp = self.get("configs").await?;
184        self.process_resp(resp).await
185    }
186
187    /// Retrieves the SRS config API description as typed summary data.
188    ///
189    /// # Errors
190    ///
191    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
192    /// for details.
193    pub async fn get_configs_summary(self) -> Result<Option<Summary>, SrsClientError> {
194        let response = self.get_configs().await?;
195        match response.data {
196            SrsClientRespData::Summary(summary) => Ok(Some(summary)),
197            _ => Err(SrsClientError::UnexpectedResponse("configs summary")),
198        }
199    }
200
201    /// Manages all vhosts or a specified vhost.
202    ///
203    /// # Errors
204    ///
205    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
206    /// for details.
207    pub async fn get_vhosts(self) -> Result<SrsClientResp, SrsClientError> {
208        let resp = self.get("vhosts").await?;
209        self.process_resp(resp).await
210    }
211
212    /// Manages a specified vhost.
213    ///
214    /// # Errors
215    ///
216    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
217    /// for details.
218    pub async fn get_vhost<T: Into<String>>(self, id: T) -> Result<SrsClientResp, SrsClientError> {
219        let resp = self.get(&format!("vhosts/{}", id.into())).await?;
220        self.process_resp(resp).await
221    }
222
223    /// Retrieves all vhosts as a typed list.
224    ///
225    /// # Errors
226    ///
227    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
228    /// for details.
229    pub async fn get_vhost_list(self) -> Result<Vec<Vhost>, SrsClientError> {
230        let response = self.get_vhosts().await?;
231        match response.data {
232            SrsClientRespData::Vhosts { vhosts } => Ok(vhosts),
233            _ => Err(SrsClientError::UnexpectedResponse("vhosts")),
234        }
235    }
236
237    /// Retrieves a specified vhost as a typed item.
238    ///
239    /// # Errors
240    ///
241    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
242    /// for details.
243    pub async fn get_vhost_item<T: Into<String>>(
244        self,
245        id: T,
246    ) -> Result<Option<Vhost>, SrsClientError> {
247        let response = self.get_vhost(id).await?;
248        match response.data {
249            SrsClientRespData::Vhost { vhost } => Ok(Some(vhost)),
250            _ => Err(SrsClientError::UnexpectedResponse("vhost")),
251        }
252    }
253
254    /// Manages all streams or a specified stream.
255    ///
256    /// # Errors
257    ///
258    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
259    /// for details.
260    pub async fn get_streams(self) -> Result<SrsClientResp, SrsClientError> {
261        let resp = self.get("streams").await?;
262        self.process_resp(resp).await
263    }
264
265    /// Manages all streams using SRS pagination.
266    ///
267    /// # Errors
268    ///
269    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
270    /// for details.
271    pub async fn get_streams_page(
272        self,
273        start: i64,
274        count: i64,
275    ) -> Result<SrsClientResp, SrsClientError> {
276        let resp = self
277            .get(&format!("streams?start={start}&count={count}"))
278            .await?;
279        self.process_resp(resp).await
280    }
281
282    /// Manages a specified stream.
283    ///
284    /// # Errors
285    ///
286    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
287    /// for details.
288    pub async fn get_stream<T: Into<String>>(self, id: T) -> Result<SrsClientResp, SrsClientError> {
289        let resp = self.get(&format!("streams/{}", id.into())).await?;
290        self.process_resp(resp).await
291    }
292
293    /// Retrieves all streams as a typed list.
294    ///
295    /// # Errors
296    ///
297    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
298    /// for details.
299    pub async fn get_stream_list(self) -> Result<Vec<Stream>, SrsClientError> {
300        let response = self.get_streams().await?;
301        match response.data {
302            SrsClientRespData::Streams { streams } => Ok(streams),
303            _ => Err(SrsClientError::UnexpectedResponse("streams")),
304        }
305    }
306
307    /// Retrieves a paginated stream response as a typed list.
308    ///
309    /// # Errors
310    ///
311    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
312    /// for details.
313    pub async fn get_stream_page_list(
314        self,
315        start: i64,
316        count: i64,
317    ) -> Result<Vec<Stream>, SrsClientError> {
318        let response = self.get_streams_page(start, count).await?;
319        match response.data {
320            SrsClientRespData::Streams { streams } => Ok(streams),
321            _ => Err(SrsClientError::UnexpectedResponse("streams page")),
322        }
323    }
324
325    /// Retrieves a specified stream as a typed item.
326    ///
327    /// # Errors
328    ///
329    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
330    /// for details.
331    pub async fn get_stream_item<T: Into<String>>(
332        self,
333        id: T,
334    ) -> Result<Option<Stream>, SrsClientError> {
335        let response = self.get_stream(id).await?;
336        match response.data {
337            SrsClientRespData::Stream { stream } => Ok(Some(stream)),
338            _ => Err(SrsClientError::UnexpectedResponse("stream")),
339        }
340    }
341
342    /// Manages all clients or a specified client, default query top 10 clients.
343    ///
344    /// # Errors
345    ///
346    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
347    /// for details.
348    pub async fn get_clients(self) -> Result<SrsClientResp, SrsClientError> {
349        let resp = self.get("clients").await?;
350        self.process_resp(resp).await
351    }
352
353    /// Manages all clients using SRS pagination.
354    ///
355    /// # Errors
356    ///
357    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
358    /// for details.
359    pub async fn get_clients_page(
360        self,
361        start: i64,
362        count: i64,
363    ) -> Result<SrsClientResp, SrsClientError> {
364        let resp = self
365            .get(&format!("clients?start={start}&count={count}"))
366            .await?;
367        self.process_resp(resp).await
368    }
369
370    /// Manages a specified client.
371    ///
372    /// # Errors
373    ///
374    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
375    /// for details.
376    pub async fn get_client<T: Into<String>>(self, id: T) -> Result<SrsClientResp, SrsClientError> {
377        let resp = self.get(&format!("clients/{}", id.into())).await?;
378        self.process_resp(resp).await
379    }
380
381    /// Retrieves all clients as a typed list.
382    ///
383    /// # Errors
384    ///
385    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
386    /// for details.
387    pub async fn get_client_list(self) -> Result<Vec<Client>, SrsClientError> {
388        let response = self.get_clients().await?;
389        match response.data {
390            SrsClientRespData::Clients { clients } => Ok(clients),
391            _ => Err(SrsClientError::UnexpectedResponse("clients")),
392        }
393    }
394
395    /// Retrieves a paginated client response as a typed list.
396    ///
397    /// # Errors
398    ///
399    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
400    /// for details.
401    pub async fn get_client_page_list(
402        self,
403        start: i64,
404        count: i64,
405    ) -> Result<Vec<Client>, SrsClientError> {
406        let response = self.get_clients_page(start, count).await?;
407        match response.data {
408            SrsClientRespData::Clients { clients } => Ok(clients),
409            _ => Err(SrsClientError::UnexpectedResponse("clients page")),
410        }
411    }
412
413    /// Retrieves a specified client as a typed item.
414    ///
415    /// # Errors
416    ///
417    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
418    /// for details.
419    pub async fn get_client_item<T: Into<String>>(
420        self,
421        id: T,
422    ) -> Result<Option<Client>, SrsClientError> {
423        let response = self.get_client(id).await?;
424        match response.data {
425            SrsClientRespData::Client { client } => Ok(Some(client)),
426            _ => Err(SrsClientError::UnexpectedResponse("client")),
427        }
428    }
429
430    /// Retrieves the supported features of SRS.
431    ///
432    /// # Errors
433    ///
434    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
435    /// for details.
436    pub async fn get_features(self) -> Result<SrsClientResp, SrsClientError> {
437        let resp = self.get("features").await?;
438        self.process_resp(resp).await
439    }
440
441    /// Retrieves the rusage of SRS.
442    ///
443    /// # Errors
444    ///
445    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
446    /// for details.
447    pub async fn get_rusages(self) -> Result<SrsClientResp, SrsClientError> {
448        let resp = self.get("rusages").await?;
449        self.process_resp(resp).await
450    }
451
452    /// Retrieves the self process stats.
453    ///
454    /// # Errors
455    ///
456    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
457    /// for details.
458    pub async fn get_self_proc_stats(self) -> Result<SrsClientResp, SrsClientError> {
459        let resp = self.get("self_proc_stats").await?;
460        self.process_resp(resp).await
461    }
462
463    /// Retrieves the system process stats.
464    ///
465    /// # Errors
466    ///
467    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
468    /// for details.
469    pub async fn get_system_proc_stats(self) -> Result<SrsClientResp, SrsClientError> {
470        let resp = self.get("system_proc_stats").await?;
471        self.process_resp(resp).await
472    }
473
474    /// Retrieves the meminfo of system.
475    ///
476    /// # Errors
477    ///
478    /// If API request cannot be performed, or fails. See [`SrsClientError`](enum@SrsClientError)
479    /// for details.
480    pub async fn get_meminfos(self) -> Result<SrsClientResp, SrsClientError> {
481        let resp = self.get("meminfos").await?;
482        self.process_resp(resp).await
483    }
484}