lenso_capability_http_client/
generated.rs1use std::{fmt, rc::Rc};
3use futures::future::LocalBoxFuture;
4use lenso_kernel::{InvocationContext, ModuleDependencies, NativeRequestEndpoint, NativeRequestFuture, NativeRequestHandle, RequestCapability, RuntimeFailure};
5
6pub const CAPABILITY_ID: &str = "lenso.http.client@1";
7pub const DESCRIPTOR_VERSION: &str = "1.0.1";
8pub const PORTABLE: bool = true;
9pub const CROSS_LANE_TRANSFER: bool = true;
10pub const CLIENT_CAPABILITY_ID: &str = CAPABILITY_ID;
11pub const CLIENT_DESCRIPTOR_VERSION: &str = DESCRIPTOR_VERSION;
12
13pub const SEND_OPERATION: &str = "send";
14
15pub use lenso_contract_runtime::{Bytes, UnknownDomainError};
16use lenso_contract_runtime::{decode_portable_json, encode_portable_json};
17
18#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
19pub struct SendRequest {
20 #[serde(rename = "body")]
21 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
22 pub body: Bytes,
23 #[serde(rename = "headers")]
24 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
25 pub headers: Vec<SendRequestHeadersItem>,
26 #[serde(rename = "method")]
27 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
28 pub method: String,
29 #[serde(rename = "url")]
30 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
31 pub url: String,
32}
33
34#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
35pub struct SendRequestHeadersItem {
36 #[serde(rename = "name")]
37 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
38 pub name: String,
39 #[serde(rename = "value")]
40 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
41 pub value: String,
42}
43
44#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
45pub struct SendResponse {
46 #[serde(rename = "body")]
47 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
48 pub body: Bytes,
49 #[serde(rename = "headers")]
50 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
51 pub headers: Vec<SendResponseHeadersItem>,
52 #[serde(rename = "status")]
53 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
54 pub status: i64,
55}
56
57#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
58pub struct SendResponseHeadersItem {
59 #[serde(rename = "name")]
60 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
61 pub name: String,
62 #[serde(rename = "value")]
63 #[serde(deserialize_with = "lenso_contract_runtime::serde::deserialize_required")]
64 pub value: String,
65}
66
67#[derive(Clone, Debug, PartialEq)]
68pub enum SendError {
69 DestinationNotAllowed,
70 InvalidRequest,
71 RequestTooLarge,
72 ResponseTooLarge,
73 Timeout,
74 TransportFailure,
75 Unknown(UnknownDomainError),
76}
77
78#[derive(Debug)]
79pub struct Client;
80impl RequestCapability for Client {
81 type Request = SendRequest;
82 type Response = SendResponse;
83 type DomainError = SendError;
84 const ID: &'static str = CAPABILITY_ID;
85 const DESCRIPTOR_VERSION: &'static str = DESCRIPTOR_VERSION;
86
87 fn invoke_native(endpoint: &dyn NativeRequestEndpoint, operation: &str, request: Self::Request, context: InvocationContext) -> NativeRequestFuture<Self> {
88 if operation != SEND_OPERATION {
89 return lenso_kernel::invoke_erased_native_request::<Self>(endpoint, operation, request, context);
90 }
91 let Some(typed_endpoint) = endpoint
92 .typed_endpoint()
93 .and_then(|endpoint| endpoint.downcast_ref::<ClientRequestEndpoint>())
94 else {
95 return lenso_kernel::invoke_erased_native_request::<Self>(endpoint, operation, request, context);
96 };
97 let provider = Rc::clone(&typed_endpoint.provider);
98 Box::pin(async move {
99 match provider.send(context, request).await {
100 Ok(value) => Ok(Ok(value)),
101 Err(ClientInvocationError::Domain(error)) => Ok(Err(error)),
102 Err(ClientInvocationError::Runtime(error)) => Err(error),
103 }
104 })
105 }
106}
107
108impl serde::Serialize for SendError {
109 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
110 where
111 S: serde::Serializer,
112 {
113 use serde::ser::SerializeMap;
114 match self {
115 Self::DestinationNotAllowed => serializer.serialize_str("destination_not_allowed"),
116 Self::InvalidRequest => serializer.serialize_str("invalid_request"),
117 Self::RequestTooLarge => serializer.serialize_str("request_too_large"),
118 Self::ResponseTooLarge => serializer.serialize_str("response_too_large"),
119 Self::Timeout => serializer.serialize_str("timeout"),
120 Self::TransportFailure => serializer.serialize_str("transport_failure"),
121 Self::Unknown(value) => {
122 let mut map = serializer.serialize_map(Some(1 + usize::from(value.payload.is_some()) + value.extra.len()))?;
123 map.serialize_entry("code", &value.code)?;
124 if let Some(payload) = &value.payload {
125 map.serialize_entry("payload", payload)?;
126 }
127 for (key, extra) in &value.extra {
128 map.serialize_entry(key, extra)?;
129 }
130 map.end()
131 },
132 }
133 }
134}
135
136impl<'de> serde::Deserialize<'de> for SendError {
137 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
138 where
139 D: serde::Deserializer<'de>,
140 {
141 let value = <serde_json::Value as serde::Deserialize>::deserialize(deserializer)?;
142 match value {
143 serde_json::Value::String(code) => match code.as_str() {
144 "destination_not_allowed" => Ok(Self::DestinationNotAllowed),
145 "invalid_request" => Ok(Self::InvalidRequest),
146 "request_too_large" => Ok(Self::RequestTooLarge),
147 "response_too_large" => Ok(Self::ResponseTooLarge),
148 "timeout" => Ok(Self::Timeout),
149 "transport_failure" => Ok(Self::TransportFailure),
150 _ => Ok(Self::Unknown(UnknownDomainError { code, payload: None, extra: std::collections::BTreeMap::new() })),
151 },
152 serde_json::Value::Object(mut object) => {
153 let Some(code) = object.remove("code").and_then(|value| value.as_str().map(ToOwned::to_owned)) else {
154 return Err(serde::de::Error::custom("Domain Error object is missing a string code"));
155 };
156 let payload = object.remove("payload");
157 let extra = object.into_iter().collect::<std::collections::BTreeMap<_, _>>();
158 Ok(Self::Unknown(UnknownDomainError { code, payload, extra }))
159 }
160 other => Err(serde::de::Error::custom(format!("Domain Error must be a string or object, got {other}"))),
161 }
162 }
163}
164
165pub fn encode_send_request(value: &SendRequest) -> Result<String, serde_json::Error> { encode_portable_json(value) }
166pub fn decode_send_request(wire: &str) -> Result<SendRequest, serde_json::Error> { decode_portable_json(wire) }
167pub fn encode_send_response(value: &SendResponse) -> Result<String, serde_json::Error> { encode_portable_json(value) }
168pub fn decode_send_response(wire: &str) -> Result<SendResponse, serde_json::Error> { decode_portable_json(wire) }
169pub fn encode_send_error(value: &SendError) -> Result<String, serde_json::Error> { encode_portable_json(value) }
170pub fn decode_send_error(wire: &str) -> Result<SendError, serde_json::Error> { decode_portable_json(wire) }
171
172pub trait ClientProvider: fmt::Debug + 'static {
173 fn send(&self, context: InvocationContext, request: SendRequest) -> LocalBoxFuture<'static, Result<SendResponse, ClientInvocationError>>;
174}
175
176#[derive(Debug)]
177struct ClientRequestEndpoint { provider: Rc<dyn ClientProvider> }
178
179#[derive(Debug)]
180pub struct ClientEndpoint<P: ClientProvider> { provider: Rc<P>, request_endpoint: ClientRequestEndpoint }
181impl<P: ClientProvider> ClientEndpoint<P> {
182 pub fn new(provider: P) -> Self {
183 let provider = Rc::new(provider);
184 let request_provider: Rc<dyn ClientProvider> = provider.clone();
185 Self { provider, request_endpoint: ClientRequestEndpoint { provider: request_provider } }
186 }
187}
188
189impl<P: ClientProvider> NativeRequestEndpoint for ClientEndpoint<P> {
190 fn capability_id(&self) -> &'static str { CAPABILITY_ID }
191 fn descriptor_version(&self) -> &'static str { DESCRIPTOR_VERSION }
192 fn operations(&self) -> &'static [&'static str] { &[
193 SEND_OPERATION,
194 ] }
195 fn typed_endpoint(&self) -> Option<&dyn std::any::Any> { Some(&self.request_endpoint) }
196 fn invoke(&self, operation: &str, request: Box<dyn std::any::Any>, context: InvocationContext) -> LocalBoxFuture<'static, Result<Result<Box<dyn std::any::Any>, Box<dyn std::any::Any>>, RuntimeFailure>> {
197 match operation {
198 SEND_OPERATION => {
199 let Ok(request) = request.downcast::<SendRequest>() else {
200 return Box::pin(futures::future::ready(Err(RuntimeFailure::ProtocolViolation { capability: CAPABILITY_ID })));
201 };
202 let provider = Rc::clone(&self.provider);
203 Box::pin(async move {
204 match provider.send(context, *request).await {
205 Ok(value) => Ok(Ok(Box::new(value) as Box<dyn std::any::Any>)),
206 Err(ClientInvocationError::Domain(error)) => Ok(Err(Box::new(error) as Box<dyn std::any::Any>)),
207 Err(ClientInvocationError::Runtime(error)) => Err(error),
208 }
209 })
210 }
211 _ => Box::pin(futures::future::ready(Err(RuntimeFailure::UnknownOperation { capability: CAPABILITY_ID, operation: operation.to_owned() }))),
212 }
213 }
214}
215
216#[derive(Debug)]
217pub struct ClientClient {
218 send: NativeRequestHandle<Client>,
219}
220impl ClientClient {
221 pub fn new(handle: NativeRequestHandle<Client>) -> Self {
222 Self { send: handle }
223 }
224
225 pub fn from_dependencies(dependencies: &ModuleDependencies) -> Result<Self, RuntimeFailure> {
226 Ok(Self {
227 send: dependencies.one::<Client>()?,
228 })
229 }
230
231 pub async fn send(&self, request: SendRequest) -> Result<SendResponse, ClientInvocationError> {
232 self.send.invoke(SEND_OPERATION, request).await
233 .map_err(ClientInvocationError::Runtime)?
234 .map_err(ClientInvocationError::Domain)
235 }
236
237 pub async fn send_with_context(&self, context: InvocationContext, request: SendRequest) -> Result<SendResponse, ClientInvocationError> {
238 self.send.invoke_with_context(SEND_OPERATION, context, request).await
239 .map_err(ClientInvocationError::Runtime)?
240 .map_err(ClientInvocationError::Domain)
241 }
242}
243
244#[derive(Clone, Debug, PartialEq)]
245pub enum ClientInvocationError {
246 Domain(SendError),
247 Runtime(RuntimeFailure),
248}