wick_config/config/components/
http_client.rs1#![allow(missing_docs)] use std::borrow::Cow;
3use std::collections::HashMap;
4
5use wick_interface_types::OperationSignatures;
6
7use super::{ComponentConfig, OperationConfig};
8use crate::config::bindings::BoundIdentifier;
9use crate::config::{self, Codec, HttpMethod};
10
11#[derive(
12 Debug,
13 Clone,
14 derive_builder::Builder,
15 PartialEq,
16 derive_asset_container::AssetManager,
17 property::Property,
18 serde::Serialize,
19)]
20#[property(get(public), set(public), mut(public, suffix = "_mut"))]
21#[asset(asset(config::AssetReference))]
22#[builder(setter(into))]
23#[must_use]
24pub struct HttpClientComponentConfig {
26 #[asset(skip)]
28 pub(crate) resource: BoundIdentifier,
29
30 #[asset(skip)]
32 #[builder(default)]
33 #[serde(skip_serializing_if = "Vec::is_empty")]
34 pub(crate) config: Vec<wick_interface_types::Field>,
35
36 #[asset(skip)]
38 #[builder(default)]
39 #[serde(skip_serializing_if = "Option::is_none")]
40 pub(crate) codec: Option<Codec>,
41
42 #[asset(skip)]
44 #[builder(default)]
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub(crate) proxy: Option<Proxy>,
47
48 #[asset(skip)]
50 #[builder(default)]
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub(crate) timeout: Option<u16>,
53
54 #[asset(skip)]
56 #[builder(default)]
57 #[property(skip)]
58 #[serde(skip_serializing_if = "Vec::is_empty")]
59 pub(crate) operations: Vec<HttpClientOperationDefinition>,
60}
61
62impl HttpClientComponentConfig {}
63
64#[derive(Debug, Clone, derive_builder::Builder, PartialEq, property::Property, serde::Serialize)]
65#[property(get(public), set(private), mut(disable))]
66#[builder(setter(into))]
67#[must_use]
68pub struct Proxy {
70 pub(crate) resource: BoundIdentifier,
72
73 #[builder(default)]
75 pub(crate) username: Option<String>,
76
77 #[builder(default)]
79 pub(crate) password: Option<String>,
80}
81
82impl Proxy {}
83
84impl OperationSignatures for HttpClientComponentConfig {
85 fn operation_signatures(&self) -> Vec<wick_interface_types::OperationSignature> {
86 let codec = self.codec;
87 self
88 .operations
89 .clone()
90 .into_iter()
91 .map(|mut op| {
92 op.codec = op.codec.or(codec);
93 op
94 })
95 .map(Into::into)
96 .collect()
97 }
98}
99
100impl ComponentConfig for HttpClientComponentConfig {
101 type Operation = HttpClientOperationDefinition;
102
103 fn operations(&self) -> &[Self::Operation] {
104 &self.operations
105 }
106
107 fn operations_mut(&mut self) -> &mut Vec<Self::Operation> {
108 &mut self.operations
109 }
110}
111
112impl OperationConfig for HttpClientOperationDefinition {
113 fn name(&self) -> &str {
114 &self.name
115 }
116
117 fn inputs(&self) -> Cow<Vec<wick_interface_types::Field>> {
118 Cow::Borrowed(&self.inputs)
119 }
120
121 fn outputs(&self) -> Cow<Vec<wick_interface_types::Field>> {
122 Cow::Owned(vec![
123 wick_interface_types::Field::new("response", wick_interface_types::Type::Object),
125 wick_interface_types::Field::new(
126 "body",
127 match self.codec {
128 Some(Codec::Json) => wick_interface_types::Type::Object,
129 Some(Codec::Raw) => wick_interface_types::Type::Bytes,
130 Some(Codec::FormData) => wick_interface_types::Type::Object,
131 Some(Codec::Text) => wick_interface_types::Type::Object,
132 None => wick_interface_types::Type::Object,
133 },
134 ),
135 ])
136 }
137}
138
139impl From<HttpClientOperationDefinition> for wick_interface_types::OperationSignature {
140 fn from(operation: HttpClientOperationDefinition) -> Self {
141 Self::new(
142 operation.name,
143 operation.inputs,
144 vec![
145 wick_interface_types::Field::new("response", wick_interface_types::Type::Object),
147 wick_interface_types::Field::new(
148 "body",
149 match operation.codec {
150 Some(Codec::Json) => wick_interface_types::Type::Object,
151 Some(Codec::Raw) => wick_interface_types::Type::Bytes,
152 Some(Codec::FormData) => wick_interface_types::Type::Object,
153 Some(Codec::Text) => wick_interface_types::Type::Object,
154 None => wick_interface_types::Type::Object,
155 },
156 ),
157 ],
158 operation.config,
159 )
160 }
161}
162
163#[derive(Debug, Clone, derive_builder::Builder, PartialEq, property::Property, serde::Serialize)]
164#[property(get(public), set(private), mut(disable))]
165#[builder(setter(into))]
166#[must_use]
167pub struct HttpClientOperationDefinition {
169 #[property(skip)]
171 pub(crate) name: String,
172
173 #[builder(default)]
175 #[serde(skip_serializing_if = "Vec::is_empty")]
176 pub(crate) config: Vec<wick_interface_types::Field>,
177
178 #[property(skip)]
180 #[serde(skip_serializing_if = "Vec::is_empty")]
181 pub(crate) inputs: Vec<wick_interface_types::Field>,
182
183 pub(crate) path: String,
185
186 #[builder(default)]
188 #[serde(skip_serializing_if = "Option::is_none")]
189 pub(crate) codec: Option<Codec>,
190
191 #[builder(default)]
193 #[serde(skip_serializing_if = "Option::is_none")]
194 pub(crate) body: Option<liquid_json::LiquidJsonValue>,
195
196 #[builder(default)]
198 #[serde(skip_serializing_if = "Option::is_none")]
199 pub(crate) headers: Option<HashMap<String, Vec<String>>>,
200
201 pub(crate) method: HttpMethod,
203}
204
205impl HttpClientOperationDefinition {
206 #[must_use]
208 pub fn new_get(
209 name: &str,
210 path: &str,
211 inputs: Vec<wick_interface_types::Field>,
212 headers: Option<HashMap<String, Vec<String>>>,
213 ) -> HttpClientOperationDefinitionBuilder {
214 let mut builder = HttpClientOperationDefinitionBuilder::default();
215 builder
216 .name(name)
217 .path(path)
218 .inputs(inputs)
219 .headers(headers)
220 .method(HttpMethod::Get);
221 builder
222 }
223
224 #[must_use]
226 pub fn new_post(
227 name: &str,
228 path: &str,
229 inputs: Vec<wick_interface_types::Field>,
230 body: Option<liquid_json::LiquidJsonValue>,
231 headers: Option<HashMap<String, Vec<String>>>,
232 ) -> HttpClientOperationDefinitionBuilder {
233 let mut builder = HttpClientOperationDefinitionBuilder::default();
234 builder
235 .name(name)
236 .path(path)
237 .inputs(inputs)
238 .body(body)
239 .headers(headers)
240 .method(HttpMethod::Post);
241 builder
242 }
243
244 #[must_use]
246 pub fn new_put(
247 name: &str,
248 path: &str,
249 inputs: Vec<wick_interface_types::Field>,
250 body: Option<liquid_json::LiquidJsonValue>,
251 headers: Option<HashMap<String, Vec<String>>>,
252 ) -> HttpClientOperationDefinitionBuilder {
253 let mut builder = HttpClientOperationDefinitionBuilder::default();
254 builder
255 .name(name)
256 .path(path)
257 .inputs(inputs)
258 .body(body)
259 .headers(headers)
260 .method(HttpMethod::Put);
261 builder
262 }
263
264 #[must_use]
266 pub fn new_delete(
267 name: &str,
268 path: &str,
269 inputs: Vec<wick_interface_types::Field>,
270 body: Option<liquid_json::LiquidJsonValue>,
271 headers: Option<HashMap<String, Vec<String>>>,
272 ) -> HttpClientOperationDefinitionBuilder {
273 let mut builder = HttpClientOperationDefinitionBuilder::default();
274 builder
275 .name(name)
276 .path(path)
277 .inputs(inputs)
278 .body(body)
279 .headers(headers)
280 .method(HttpMethod::Delete);
281 builder
282 }
283}