I want to have a context-struct that is available in all handlers, but I am not able to get trough the compiler.
For an example, I want something like this
extern crate iron;
extern crate router;
use iron::prelude::*;
use router::Router;
use std::collections::HashMap;
struct Context {
cache: HashMap<String, String>,
}
fn main() {
let mut context = Context { cache: HashMap::new(), };
let mut router = Router::new();
router.get("/", |request| index(request, context));
Iron::new(router).http("localhost:80").unwrap();
}
fn index(_: &mut Request, context: Context) -> IronResult<Response> {
Ok(Response::with((iron::status::Ok, "index")))
}
This won't compile with a lengthy error message
error: type mismatch resolving `for<'r, 'r, 'r> <[closure@src\main.rs:... context:_] as std::ops::FnOnce<(&'r mut iron::Request<'r, 'r>,)>>::Output == std::result::Result<iron::Response, iron::IronError>`:
expected bound lifetime parameter ,
found concrete lifetime [E0271]
src\main.rs:... router.get("/", |request| index(request, context));
The error message is almost incomprehensible here (there is a issue for it!).
The problem is that the type of the closure is not being inferred. We can help the compiler annotating the type of request
:
extern crate iron;
extern crate router;
use iron::prelude::*;
use router::Router;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
#[derive(Clone, Default)]
struct Context {
cache: Arc<Mutex<HashMap<String, String>>>,
}
fn main() {
let context = Context::default();
let mut router = Router::new();
let c = context.clone();
router.get("/", move |request: &mut Request| index(request, &c), "index");
Iron::new(router).http("localhost:8080").unwrap(); // port 80 is privileged
}
fn index(_: &mut Request, context: &Context) -> IronResult<Response> {
Ok(Response::with((iron::status::Ok, "index")))
}
Note that I changed the type of context
to &Context
(otherwise, the closure would only implements FnOnce
) and use move
(the closure must have 'static
lifetime to implement Handler
).
To make it possible to change cache
in index
, you will have to change the type to Arc<Mutex<HashMap<String, String>>>
or similar.