Rust 如何实现一个“动态列表”;“中间件”;功能?

Rust 如何实现一个“动态列表”;“中间件”;功能?,rust,Rust,我正在编写一些代码,其结构类似于web框架中的“中间件”,因此我将在这个简单的示例中使用该术语。中间件功能的思想是它包装了实际的响应处理程序,因此它可以在请求到达处理程序之前修改请求,并在响应返回后修改响应: struct请求; 结构反应; 特质处理者{ fn handle(&self,request:request)->Response; } 特征中间件{ fn handle(&self,request:request,next:Box Response>)->Response; } 我考虑

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

struct请求;
结构反应;
特质处理者{
fn handle(&self,request:request)->Response;
}
特征中间件{
fn handle(&self,request:request,next:Box Response>)->Response;
}
我考虑过使用两个单独的函数,一个用于预处理请求,另一个用于后处理响应,但是如果不借助黑客,我将无法在请求期间存储任何附加状态

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

struct服务器{
处理者:盒子,
中间产品:Vec,
}
现在,如何实现响应处理?以下是我的两次尝试:

impl服务器{
//第一次尝试:使用迭代器::fold()
fn处理请求折叠响应{
让handler\u with\u middleware=self.middleware.iter()
.rev()
.fold:(&'a self,request:request,index:usize)->响应{
如果索引>=self.middleware.len(){
self.handler.handle(请求)
}否则{
让下一步=框::新建(
|r:Request | self.handle_Request_from(r,index+1));
self.middleware[index].handle(请求,下一个)
}
}
}
两次尝试都给出了相同的错误,这表明我在做一些根本错误的事情:

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
error[E0759]:'self'具有生存期''a',但它需要满足''static'生存期要求
-->src/lib.rs:25:67
|
19 | fn处理|请求|折叠响应{
|-----此数据的生存期为“'a”。。。
...
25 | Box::new(| request | middleware.handle(request,next))
|^^^^…被捕获,并且需要在这里保持“静态”
我知道trait对象有一个隐式的
'静态的
生存期,所以我尝试添加显式的生存期,正如你所看到的,但是没有帮助。我不明白为什么编译器会在这里的任何地方要求一个
'静态的
生存期;没有任何东西(包括闭包)可以逃脱
句柄请求*
函数,对吗


发布之后,我发现:传递给
中间件的装箱trait对象也需要一个非
静态的
生存期

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

有必要让中间件接受动态函数对象吗?我看不出全部情况,但对我来说,在构建中间件之后,您不太可能需要热交换这些函数。如果您需要另一个函数,您可以制作另一个中间件(因此你可以放弃泛型,而不需要在通过中间件的过程中生成数百万个盒子)@AlexLarionov它实际上不是我正在开发的一个web应用程序,而是一个数据处理管道在运行时从YAML文件加载。每个文件只调用一次,因此装箱的开销可以忽略不计。
    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)
        }
    }