openlark_platform/app_engine/apaas/v1/application/function/
invoke.rs1use openlark_core::{
7 SDKResult,
8 api::{ApiRequest, ApiResponseTrait, ResponseFormat},
9 config::Config,
10 http::Transport,
11 req_option::RequestOption,
12};
13use serde::{Deserialize, Serialize};
14
15#[derive(Debug, Clone)]
17pub struct FunctionInvokeRequestBuilder {
18 config: Config,
19 namespace: String,
21 function_api_name: String,
23 params: serde_json::Value,
25}
26
27impl FunctionInvokeRequestBuilder {
28 pub fn new(
30 config: Config,
31 namespace: impl Into<String>,
32 function_api_name: impl Into<String>,
33 ) -> Self {
34 Self {
35 config,
36 namespace: namespace.into(),
37 function_api_name: function_api_name.into(),
38 params: serde_json::json!({}),
39 }
40 }
41
42 pub fn params(mut self, params: impl Into<serde_json::Value>) -> Self {
44 self.params = params.into();
45 self
46 }
47
48 pub async fn execute(self) -> SDKResult<FunctionInvokeResponse> {
50 self.execute_with_options(RequestOption::default()).await
51 }
52
53 pub async fn execute_with_options(
55 self,
56 option: RequestOption,
57 ) -> SDKResult<FunctionInvokeResponse> {
58 let url = format!(
59 "/open-apis/apaas/v1/applications/{}/functions/{}/invoke",
60 self.namespace, self.function_api_name
61 );
62
63 let request = FunctionInvokeRequest {
64 params: self.params,
65 };
66
67 let req: ApiRequest<FunctionInvokeResponse> =
68 ApiRequest::post(&url).body(serde_json::to_value(&request)?);
69 Transport::request_typed(req, &self.config, Some(option), "Operation").await
70 }
71}
72
73#[derive(Debug, Clone, Deserialize, Serialize)]
75struct FunctionInvokeRequest {
76 #[serde(rename = "params")]
78 params: serde_json::Value,
79}
80
81#[derive(Debug, Clone, Deserialize, Serialize)]
83pub struct FunctionInvokeResponse {
84 #[serde(rename = "result")]
86 pub result: serde_json::Value,
87 #[serde(rename = "status")]
89 pub status: String,
90 #[serde(rename = "message")]
92 pub message: String,
93}
94
95impl ApiResponseTrait for FunctionInvokeResponse {
96 fn data_format() -> ResponseFormat {
97 ResponseFormat::Data
98 }
99}
100
101#[deprecated(note = "renamed to FunctionInvokeRequestBuilder, will be removed in v1.0 (#271)")]
103pub type FunctionInvokeBuilder = FunctionInvokeRequestBuilder;
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[tokio::test]
111 async fn test_invoke_function_returns_data_on_success() {
112 use serde_json::json;
113 use wiremock::MockServer;
114 use wiremock::matchers::{method, path};
115 use wiremock::{Mock, ResponseTemplate};
116
117 let server = MockServer::start().await;
118 Mock::given(method("POST"))
119 .and(path(
120 "/open-apis/apaas/v1/applications/ns_test/functions/func_001/invoke",
121 ))
122 .respond_with(ResponseTemplate::new(200).set_body_json(json!({
123 "code": 0,
124 "msg": "success",
125 "data": {
126 "result": {"output": "ok"},
127 "status": "SUCCESS",
128 "message": "执行成功"
129 }
130 })))
131 .mount(&server)
132 .await;
133
134 let config = Config::builder()
135 .app_id("ci_app_id")
136 .app_secret("ci_app_secret")
137 .base_url(server.uri())
138 .enable_token_cache(false)
139 .build();
140
141 let resp = FunctionInvokeRequestBuilder::new(config, "ns_test", "func_001")
142 .params(json!({"arg": 1}))
143 .execute()
144 .await
145 .expect("执行函数应成功");
146 assert_eq!(resp.status, "SUCCESS");
147 assert_eq!(resp.message, "执行成功");
148 assert_eq!(resp.result["output"], "ok");
149
150 let received = server.received_requests().await.unwrap_or_default();
151 assert_eq!(received.len(), 1);
152 assert_eq!(
153 received[0].url.path(),
154 "/open-apis/apaas/v1/applications/ns_test/functions/func_001/invoke"
155 );
156 }
157}