Пожизненная проблема с Actix Web
Я внедряю промежуточное ПО с 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
также ссылка.
Я не понимаю, почему компилятор сказал the lifetime cannot outlive the anonymous lifetime #1
, Из того, что я могу сказать, это то, что cache_addr
Пожизненная до сих пор переживает закрытие. Срок службы должен покрывать до system.run()
линия. Может ли кто-нибудь просветить меня?
Редактировать:
Я обновил приведенный выше код до MCVE (по крайней мере до такой степени, что достаточно просто скопировать весь код и запустить сборку груза, сохраняя при этом то же сообщение об ошибке). Я не могу запустить его на ржавой площадке. Не поддерживает actix
ящик в этой точке. Я попытался уменьшить это дальше, но это дает мне другую ошибку. Извините, я довольно новичок в Rust.
У меня двоякие вопросы, мне нравится понимать, что говорит мне ошибка. Во-вторых, мне нравится знать, как правильно сделать это с actix
таким образом, почему пример кода зависит от actix
,
1 ответ
Посмотрите на App::route
подпись:
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
родовое зависит от T
а также R
что в свою очередь есть 'static
пожизненное требование
Ваше закрытие захватывает &Addr<CacheActor>
что это не действительно для 'static
время жизни, и это генерирует ошибку.
Я вижу возможность использовать App
"Государство", прямо из документов:
Состояние приложения используется всеми маршрутами и ресурсами в одном приложении. При использовании субъекта http доступ к состоянию можно получить с помощью HttpRequest::state() только для чтения, но внутреннюю изменчивость с помощью RefCell можно использовать для достижения изменчивости состояния. Состояние также доступно для предикатов и промежуточных программ сопоставления маршрутов.
В этом случае должно быть что-то вроде:
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();
}