Reputation: 15
I'm trying to create a middleware with redis and actix-web.
This is what I want for my middleware:
-> Concat the request path and query_string, to create a redis key.
-> Get the value stored within redis db.
-> If not null, return this content.
-> If null, call the next service, and once it's done, store the response within redis (so it's cached for next time)
My issue is that inside my wrap_fn
function I need to get the async result of redis before I try to call srv.call(req)
Let me explain:
.wrap_fn(|req, srv| {
let fut = srv.call(req);
async {
let mut res = fut.await?;
Ok(res)
}
})
This code work, so we get the future response within fut
, then we await and respond.
Now if I want to add my logic to it:
.wrap_fn(|req, srv| {
let path = req.path().to_string();
let query_string = req.query_string().to_string();
let redis_fut = async move {
let redis_key = format!("{}:{}", path, query_string);
redis.get(redis_key.as_str()).await
};
// let fut = srv.call(req);
async {
let redis_res: String = redis_fut.await?.unwrap();
if redis_res.ne(format!("(nil)")) {
// Build and return redis content
}
else {
let mut res = srv.call(req).await?; // Moved srv.call(req) here
// Add to redis
Ok(res)
}
}
})
I must move let fut = srv.call(req);
inside the async block because otherwise it will get executed even if there is a redis result.
But It doesn't work because of the lifetime of srv
.
error: lifetime may not live long enough
--> src/main.rs:90:4
|
74 | .wrap_fn(|req, srv| {
| ---- return type of closure `impl futures::Future<Output = Result<ServiceResponse, actix_web::Error>>` contains a lifetime `'2`
| |
| has type `&'1 actix_web::app_service::AppRouting`
...
90 | / async {
91 | | let res = srv.call(req).await?;
92 | | Ok(res)
93 | | }
| |_____________^ returning this value requires that `'1` must outlive `'2`
How can I achieve this?
Upvotes: 0
Views: 382