gpt4 book ai didi

rust - 如何实现动态列表 "middleware"函数?

转载 作者:行者123 更新时间:2023-12-03 11:26:50 25 4
gpt4 key购买 nike

我正在编写一些代码,其结构类似于网络框架中的“中间件”,因此我将在这个最小示例中使用该术语。中间件函数的想法是它包装了实际的响应处理程序,因此它可以在请求到达处理程序之前修改请求,并在返回后修改响应:

struct Request;
struct Response;

trait Handler {
fn handle(&self, request: Request) -> Response;
}

trait Middleware {
fn handle(&self, request: Request, next: Box<dyn FnOnce(Request) -> Response>) -> Response;
}

我考虑过使用两个独立的函数,一个用于预处理请求,一个用于后处理响应,但是如果不诉诸 hack,我将无法在请求期间存储任何额外的状态。

服务器包含动态配置处理程序和中间件,因此它必须使用一些盒装特征对象:

struct Server {
handler: Box<dyn Handler>,
middlewares: Vec<Box<dyn Middleware>>,
}

现在,如何实现响应处理?这是我的两次尝试:

impl Server {
// First attempt: using Iterator::fold()
fn handle_request_fold<'a>(&'a self, request: Request) -> Response {
let handler_with_middlewares = self.middlewares.iter()
.rev()
.fold::<Box<dyn FnOnce(Request) -> Response + 'a>, _>(
Box::new(|request| self.handler.handle(request)),
|next, middleware| {
Box::new(|request| middleware.handle(request, next))
}
);
handler_with_middlewares(request)
}

// Second attempt: using recursion
fn handle_request_recurse(&self, request: Request) -> Response {
self.handle_request_from(request, 0)
}

fn handle_request_from<'a>(&'a self, request: Request, index: usize) -> Response {
if index >= self.middlewares.len() {
self.handler.handle(request)
} else {
let next = Box::new(
|r: Request| self.handle_request_from(r, index + 1));
self.middlewares[index].handle(request, next)
}
}
}

两次尝试都给出了相同的错误,这表明我在这里做的根本错误:

error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
--> src/lib.rs:25:67
|
19 | fn handle_request_fold<'a>(&'a self, request: Request) -> Response {
| -------- this data with lifetime `'a`...
...
25 | Box::new(|request| middleware.handle(request, next))
| ^^^^ ...is captured and required to live as long as `'static` here

我知道 trait 对象有一个隐式的 'static 生命周期,所以我尝试添加显式生命周期,如您所见,但没有帮助。我不明白为什么编译器会在这里的任何地方要求 'static 生命周期;没有什么(包括闭包)可以逃脱 handle_request_* 函数,对吧?

Playground link

最佳答案

在发布之后,我想通了:传递给 Middleware 的盒装特征对象也需要非 'static 生命周期。

trait Middleware {
fn handle<'a>(&self, request: Request,
next: Box<dyn FnOnce(Request) -> Response + 'a>)
-> Response;
}
    fn handle_request_from(&self, request: Request, index: usize) -> Response {
if index >= self.middlewares.len() {
self.handler.handle(request)
} else {
let next = Box::new(
move |request| self.handle_request_from(request, index + 1));
self.middlewares[index].handle(request, next)
}
}

关于rust - 如何实现动态列表 "middleware"函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64768036/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com