gpt4 book ai didi

rust - Actix Web 的终身问题

转载 作者:行者123 更新时间:2023-11-29 08:18:18 25 4
gpt4 key购买 nike

我正在使用 Actix-web 实现中间件,但遇到了一个我无法弄清楚的生命周期问题。

extern crate actix_web;

use actix_web::actix::{Actor, Addr, Context, System};
use actix_web::middleware::Middleware;
use actix_web::{http, server, App, HttpRequest, Responder};
use std::collections::HashMap;

pub struct CacheActor {
caches: HashMap<String, String>,
}

impl CacheActor {
pub fn new() -> Self {
CacheActor {
caches: HashMap::new(),
}
}
}

impl Actor for CacheActor {
type Context = Context<Self>;
}

fn create_resource(req: HttpRequest, addr: &Addr<CacheActor>) -> impl Responder {
unimplemented!();
format!("Unimplemented")
}

fn list_resources(req: HttpRequest, addr: &Addr<CacheActor>) -> impl Responder {
unimplemented!();
format!("Unimplemented")
}

pub trait TusMiddlewareTrait {
fn with_tus(self, addr: &Addr<CacheActor>) -> App;
}

impl TusMiddlewareTrait for App {
fn with_tus(self, addr: &Addr<CacheActor>) -> App {
self.route("/files", http::Method::GET, |req| list_resources(req, addr))
.route("/files", http::Method::POST, |req| {
create_resource(req, addr)
})
}
}

fn main() {
let system = System::new("Example");
let cache_addr = CacheActor::new().start();

server::new(|| App::new().with_tus(&cache_addr))
.bind("127.0.0.1:8080")
.unwrap()
.run();

system.run();
}

我得到的错误如下,

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/tus/middleware.rs:84:49
|
84 | .route("/files", http::Method::GET, |req| list_resources(req, addr))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 81:5...
--> src/tus/middleware.rs:81:5
|
81 | / fn with_tus(self, addr: &actix::Addr<cache::CacheActor>) -> App {
82 | | self.middleware(TusMiddleware)
83 | | .route("/files", http::Method::OPTIONS, tus_information)
84 | | .route("/files", http::Method::GET, |req| list_resources(req, addr))
... |
87 | | })
88 | | }
| |_____^
= note: ...so that the types are compatible:
expected &&actix::address::Addr<tus::cache::CacheActor>
found &&actix::address::Addr<tus::cache::CacheActor>
= note: but, the lifetime must be valid for the static lifetime...

至于我的理解,我正在传递 cache_addr 作为对 with_tus 函数的引用。在route 中的每个闭包中,addr 也是一个引用。

我不明白为什么编译器说生命周期不能超过匿名生命周期#1。据我所知,cache_addr 的生命周期仍然比闭包长。生命周期应该覆盖到 system.run() 行。谁能赐教一下?

编辑:

我将上面的代码更新为 MCVE(至少在某种程度上它足够简单,可以复制整个代码并运行 cargo build,同时仍然保留相同的错误消息)。我不能在 rust-playground 上运行它。目前它不支持 actix crate。我尝试进一步减少它,但它给了我一个不同的错误。抱歉,我是 Rust 的新手。

我的问题有两个,一个是我想了解错误告诉我的是什么。其次,我想知道如何使用 actix 正确执行此操作,因此示例代码依赖于 actix 的原因。

最佳答案

查看 App::route signature :

pub fn route<T, F, R>(self, path: &str, method: Method, f: F) -> App<S> 
where
F: WithFactory<T, S, R>,
R: Responder + 'static,
T: FromRequest<S> + 'static,

F通用取决于 TR反过来有 'static生命周期要求。

你的闭包捕获了一个 &Addr<CacheActor>它对 'static 无效生命周期,这会产生错误。

我看到的一种可能性是使用 App “状态”,直接来自 docs :

Application state is shared with all routes and resources within the same application. When using an http actor, state can be accessed with the HttpRequest::state() as read-only, but interior mutability with RefCell can be used to achieve state mutability. State is also available for route matching predicates and middlewares.

在这种情况下应该是这样的:

extern crate actix_web;

use actix_web::actix::{Actor, Addr, Context, System};
use actix_web::{http, server, App, HttpRequest, HttpResponse, Result};
use std::collections::HashMap;
use actix_web::dev::Handler;

#[derive(Clone)]
pub struct CacheActor {
caches: HashMap<String, String>,
}

impl CacheActor {
pub fn new() -> Self {
CacheActor {
caches: HashMap::new(),
}
}
}

impl Actor for CacheActor {
type Context = Context<Self>;
}

impl<S> Handler<S> for CacheActor {
type Result = String;

fn handle(&self, _req: &HttpRequest<S>) -> Self::Result {
unimplemented!();
}
}

fn list_resources(req: &HttpRequest<Addr<CacheActor>>) -> Result<HttpResponse> {
Ok(HttpResponse::Found()
.header(http::header::LOCATION, format!("hello {}", req.path()))
.finish())
}

fn main() {
let system = System::new("Example");

server::new(|| {
let cache_addr = CacheActor::new().start();
App::with_state(cache_addr)
.resource("/world", |r| r.method(http::Method::GET).f(list_resources))
})
.bind("127.0.0.1:8080")
.unwrap()
.run();

system.run();
}

关于rust - Actix Web 的终身问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53465548/

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