AWS lambda rust - 如何使函数返回外部闭包?
我正在使用 rust-aws-lambda 项目。我的用例是使用 Lambda 作为 API 网关代理。此外,我正在使用闭包,如 此示例,因为我想在 lambda 代码中使用共享资源,例如客户端和秘密值(从 AWS Secrets Manager 检索)。
我长期以来一直困扰的问题是如何将闭包抽象为另一个辅助函数。例如,我希望该函数在这种情况下返回外部闭包。我已经尝试过,但我无法让 Rust 编译器让我这样做。
这两个闭包都在 main
函数内。根据列出的示例,我的内部闭包定义如下:
let handler_func_closure = move |event: ApiProxyRequest| async move {
...
Ok::<_, Error>(success_resp)
};
这些是代码中的相关导入:
use lambda_http::{service_fn, Body, Error, IntoResponse, Request as ApiProxyRequest, RequestExt};
use lambda_http::tower::util::ServiceFn;
我在 main.rs< 的 async
main
函数中定义了以下闭包/code>,到目前为止对我有用。
let outer_closure = move |event: ApiProxyRequest| async move {
match handler_func_closure(event).await {
Ok(s) => Ok(s.into_response()),
Err(e) => Ok(http::Response::builder()
.header(http::header::CONTENT_TYPE, "application/json")
.status(400)
.body(
serde_json::to_string(&json!({"error": &err.to_string()}))
.expect("unable to serialize serde_json::Value")
.into(),
)
.expect("unable to build http::Response")),
}
};
其中 into_response()
由从特征 IntoResponse
实现的结构来满足。
所以基本上我想做的是创建一个返回闭包的函数,可以传递给service_fn
。以下是我迄今为止的尝试 - 但目前还不能满足 Rust 编译器的要求。
pub fn get_service_fn<T, T2, F, F2, I: IntoResponse>(handler_func_closure: T) -> ServiceFn<T2>
where T: Fn(http::Request<Body>) -> F + Send + Sync,
T2: Fn(lambda_http::Request) -> F2,
F2: Future<Output=crate::Result<http::Response<Body>>>,
F: Future<Output=crate::Result<I>> + Send {
let outer_closure = move |event: ApiProxyRequest| async move {
match handler_func_closure(event).await {
Ok(s) => Ok(s.into_response()),
Err(e) => failure(Box::new(e), None),
}
};
service_fn(outer_closure)
};
我见过其他关于如何函数返回闭包的问题,但我似乎无法让它在这种情况下工作。我很想知道是否有人能够使其工作,其中函数返回的外部闭包可以传递给service_fn
。
我觉得我花了无数的时间试图解决这个问题,但我一直无法让它发挥作用。老实说,我不完全确定这在 Rust 中是否可能,但我很好奇是否有人知道如何解决这个问题。
编辑:这是我收到的编译器错误,以防有帮助:
error[E0308]: mismatched types
--> src/bin/my_lambda/main.rs:197:16
|
185 | pub fn get_service_fn<T, T2, F, F2, I: IntoResponse>(handler_func_closure: T) -> ServiceFn<T2>
| -- this type parameter
...
190 | let outer_closure = move |event: ApiProxyRequest| async move {
| __________________________-________________________________________-
| | _________________________|
| ||
191 | || match handler_func_closure(event).await {
192 | || Ok(s) => Ok(s.into_response()),
193 | || Err(e) => failure(Box::new(e), None),
194 | || }
195 | || };
| || -
| ||_____|
| |______the found closure
| the found `async` block
196 |
197 | service_fn(outer_closure)
| ^^^^^^^^^^^^^ expected type parameter `T2`, found closure
|
::: /Users/rnag/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/future/mod.rs:61:43
|
61 | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
| ------------------------------- the found opaque type
|
= note: expected type parameter `T2`
found closure `[closure@src/bin/my_lambda/main.rs:190:25: 195:6]`
= help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `T2`
I am using rust-aws-lambda
project. My use case is with Lambda as an API Gateway Proxy. Additionally I am using closures as explained in this example, as I want to use shared resources such as clients and secret value (retrieved from AWS Secrets Manager) in my lambda code.
The issue I am struggling with for long time is how I can abstract the closures into another helper function. I want the function to return the outer closure in this case, for example. I have tryd but I cannot get Rust compiler to let me do this.
The both closures are within main
function. Per the listed example, my inner closure is defined something like this:
let handler_func_closure = move |event: ApiProxyRequest| async move {
...
Ok::<_, Error>(success_resp)
};
These are my relevant imports in the code:
use lambda_http::{service_fn, Body, Error, IntoResponse, Request as ApiProxyRequest, RequestExt};
use lambda_http::tower::util::ServiceFn;
I have below closure which I have defined in async main
function in main.rs
, which is working for me so far.
let outer_closure = move |event: ApiProxyRequest| async move {
match handler_func_closure(event).await {
Ok(s) => Ok(s.into_response()),
Err(e) => Ok(http::Response::builder()
.header(http::header::CONTENT_TYPE, "application/json")
.status(400)
.body(
serde_json::to_string(&json!({"error": &err.to_string()}))
.expect("unable to serialize serde_json::Value")
.into(),
)
.expect("unable to build http::Response")),
}
};
Where into_response()
is satisfied by a struct implementing from trait IntoResponse
.
So basically what I'm trying to do is make a function to return closure that can be passed in to service_fn
. Below is my attempt so far - but it's not satisfy Rust compiler currently.
pub fn get_service_fn<T, T2, F, F2, I: IntoResponse>(handler_func_closure: T) -> ServiceFn<T2>
where T: Fn(http::Request<Body>) -> F + Send + Sync,
T2: Fn(lambda_http::Request) -> F2,
F2: Future<Output=crate::Result<http::Response<Body>>>,
F: Future<Output=crate::Result<I>> + Send {
let outer_closure = move |event: ApiProxyRequest| async move {
match handler_func_closure(event).await {
Ok(s) => Ok(s.into_response()),
Err(e) => failure(Box::new(e), None),
}
};
service_fn(outer_closure)
};
I have seen other question asked on how can function return closure, but I cannot seem to get it to work in this case. I am curious to know if anyone able to get this to work where an outer closure returned by a function can be passed in to service_fn
.
I feel like I've spent countless hours in trying to figure this out, but I've been unable to make it work. I'm not entirely sure whether this is possible in Rust to be honest, but I'd be curious if anyone has an idea how to approach this.
Edit: This is the compiler error I'm getting in case it's helpful:
error[E0308]: mismatched types
--> src/bin/my_lambda/main.rs:197:16
|
185 | pub fn get_service_fn<T, T2, F, F2, I: IntoResponse>(handler_func_closure: T) -> ServiceFn<T2>
| -- this type parameter
...
190 | let outer_closure = move |event: ApiProxyRequest| async move {
| __________________________-________________________________________-
| | _________________________|
| ||
191 | || match handler_func_closure(event).await {
192 | || Ok(s) => Ok(s.into_response()),
193 | || Err(e) => failure(Box::new(e), None),
194 | || }
195 | || };
| || -
| ||_____|
| |______the found closure
| the found `async` block
196 |
197 | service_fn(outer_closure)
| ^^^^^^^^^^^^^ expected type parameter `T2`, found closure
|
::: /Users/rnag/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/future/mod.rs:61:43
|
61 | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
| ------------------------------- the found opaque type
|
= note: expected type parameter `T2`
found closure `[closure@src/bin/my_lambda/main.rs:190:25: 195:6]`
= help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `T2`
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论