I’m trying to process the result of a redis future, generated by redis-async:
pub type MiddlewareFuture = Box<Future<Item=(), Error=PathfinderError> + 'static>;
impl Middleware for JwtTokenMiddleware {
fn process_request(&self, message: &JsonMessage, handle: &Handle) -> MiddlewareFuture {
let token = match message["token"].as_str() {
Some(token) => String::from(token),
None => {
return Box::new(lazy(move || {
let message = String::from("Token was not specified.");
Err(PathfinderError::AuthenticationError(message))
}))
}
};
let redis_socket_address = self.redis_address.parse().unwrap();
let redis_connection = paired_connect(&redis_socket_address, handle);
Box::new(
redis_connection
// Get the User ID from Redis by the token
.and_then(move |connection| {
connection.send::<String>(resp_array!["GET", token])
})
// Connection issue or token is already deleted
.map_err(|err| {
let message = String::from("Token is expired.");
Err(PathfinderError::AuthenticationError(message))
})
// Extracted user_id used here for additional JWT validation
.map(|user_id| {
let validation_struct = self.get_validation_struct(&user_id);
validate_token(&token, &self.jwt_secret, &validation_struct)
})
.map_err(|_| {
let message = String::from("Token is invalid.");
Err(PathfinderError::AuthenticationError(message))
})
.map(|_| { Ok(()) })
)
}
}
This future will be fired and an execution result will be processing further, during processing client requests:
let ws_reader = stream.for_each(move |message: Message| {
// ...
// Apply a middleware to each incoming message
let auth_future = auth_middleware_local.borrow()
.process_request(&json_message, &handle_inner)
.then(move |result| {
if result.is_err() {
let tx_nested = &connections_nested.borrow_mut()[&addr];
let formatted_error = format!("{}", result.unwrap_err());
let error_message = engine_nested.borrow().wrap_an_error(formatted_error.as_str());
tx_nested.unbounded_send(error_message).unwrap();
};
Ok(())
});
handle_inner.spawn(auth_future);
Ok(())
});
But any of my attempts in conversion (like dropping a result, because I don’t care about if, if the token is valid) are leads to errors and warnings on the compiler step:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/token/middleware.rs:91:9
|
91 | / Box::new(
92 | | redis_connection
93 | | // Get the User ID from Redis by the token
94 | | .and_then(move |connection| {
... |
111 | | .map(|_| ())
112 | | )
| |_________^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 78:5...
--> src/token/middleware.rs:78:5
|
78 | / fn process_request(&self, message: &JsonMessage, handle: &Handle) -> MiddlewareFuture {
79 | | let token = match message["token"].as_str() {
80 | | Some(token) => String::from(token),
81 | | None => {
... |
112 | | )
113 | | }
| |_____^
note: ...so that the type `futures::Map<futures::MapErr<futures::Map<futures::MapErr<futures::AndThen<std::boxed::Box<futures::Future<Item=redis_async::client::PairedConnection, Error=redis_async::error::Error>>, std::boxed::Box<futures::Future<Item=std::string::String, Error=redis_async::error::Error>>, [closure@src/token/middleware.rs:94:27: 96:18 token:std::string::String]>, [closure@src/token/middleware.rs:98:26: 101:18]>, [closure@src/token/middleware.rs:103:22: 106:18 self:&&token::middleware::JwtTokenMiddleware, token:&std::string::String]>, [closure@src/token/middleware.rs:107:26: 110:18]>, [closure@src/token/middleware.rs:111:22: 111:28]>` will meet its required lifetime bounds
--> src/token/middleware.rs:91:9
|
91 | / Box::new(
92 | | redis_connection
93 | | // Get the User ID from Redis by the token
94 | | .and_then(move |connection| {
... |
111 | | .map(|_| ())
112 | | )
| |_________^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that expression is assignable (expected std::boxed::Box<futures::Future<Item=(), Error=error::PathfinderError> + 'static>, found std::boxed::Box<futures::Future<Item=(), Error=error::PathfinderError>>)
--> src/token/middleware.rs:91:9
|
91 | / Box::new(
92 | | redis_connection
93 | | // Get the User ID from Redis by the token
94 | | .and_then(move |connection| {
... |
111 | | .map(|_| ())
112 | | )
| |_________^
Any ideas how it could be fixed? Perhaps for futures already exists any convention about processing different future types and transforming it to an another types?