drogue_client/command/v1/
client.rs1use crate::core::CoreClient;
2use crate::error::ClientError;
3use crate::openid::TokenProvider;
4use serde::Serialize;
5use std::{fmt::Debug, sync::Arc};
6use tracing::instrument;
7use url::Url;
8
9#[derive(Clone, Debug)]
11pub struct Client {
12 client: reqwest::Client,
13 api_url: Url,
14 token_provider: Arc<dyn TokenProvider>,
15}
16
17type ClientResult<T> = Result<T, ClientError>;
18
19impl CoreClient for Client {
20 fn client(&self) -> &reqwest::Client {
21 &self.client
22 }
23
24 fn token_provider(&self) -> &dyn TokenProvider {
25 self.token_provider.as_ref()
26 }
27}
28
29impl Client {
30 pub fn new(
32 client: reqwest::Client,
33 api_url: Url,
34 token_provider: impl TokenProvider + 'static,
35 ) -> Self {
36 Self {
37 client,
38 api_url,
39 token_provider: Arc::new(token_provider),
40 }
41 }
42
43 fn url(&self, application: &str, device: &str) -> ClientResult<Url> {
44 let mut url = self.api_url.clone();
45
46 {
47 let mut path = url
48 .path_segments_mut()
49 .map_err(|_| ClientError::Request("Failed to get paths".into()))?;
50
51 path.extend(&[
52 "api",
53 "command",
54 "v1alpha1",
55 "apps",
56 application,
57 "devices",
58 device,
59 ]);
60 }
61
62 Ok(url)
63 }
64
65 #[instrument(skip(payload))]
70 pub async fn publish_command<A, D, C, P>(
71 &self,
72 application: A,
73 device: D,
74 command: C,
75 payload: Option<P>,
76 ) -> ClientResult<Option<()>>
77 where
78 A: AsRef<str> + Debug,
79 D: AsRef<str> + Debug,
80 C: AsRef<str> + Debug,
81 P: Serialize + Send + Sync,
82 {
83 let url = self.url(application.as_ref(), device.as_ref())?;
84 let query = vec![("command".to_string(), command.as_ref().to_string())];
85
86 self.create_with_query_parameters(url, payload, Some(query))
87 .await
88 }
89}