我最终使用了一个包装器:
pub trait SessionHandler {
fn session_manager(&self) -> &SessionManager;
fn authenticated(&self) -> bool {
false
}
fn handle_session(&self, session: &mut Session, req: &mut Request) -> IronResult<Response>;
fn handle(&self, req: &mut Request) -> IronResult<Response> {
let mut session = match self.session_manager().get_request_session(req) {
None => return Ok(Response::with((status::Unauthorized, ""))),
Some(session) => {
if self.authenticated() {
if let None = session.user_id {
return Ok(Response::with((status::Forbidden, "")));
}
}
session
}
};
self.handle_session(&mut session, req)
}
}
pub struct SessionHandlerBox<T> {
pub s: T
}
impl <T> Handler for SessionHandlerBox<T> where T: SessionHandler + Send + Sync + 'static {
fn handle(&self, r: &mut Request) -> IronResult<Response> {
self.s.handle(r)
}
}
所以我使用:
struct FileDelete {
db: Arc<Pool<PostgresConnectionManager>>,
sm: Arc<SessionManager>,
}
impl SessionHandler for FileDelete {
fn session_manager(&self) -> &SessionManager {
self.sm.as_ref()
}
fn handle_session(&self, session: &mut Session, req: &mut Request) -> IronResult<Response> {
Ok(Response::with((status::Ok, "")))
}
}
仍然有样板,但“业务逻辑”较少。欢迎任何更好的解决方案。
用法示例:
pub fn register_handlers<'s>(db: Pool<PostgresConnectionManager>, r: &'s mut Router, sm : Arc<SessionManager>) {
let file_delete = FileDelete { db: Arc::new(db), sm: sm.clone() };
r.delete("/file", SessionHandlerBox {s: file_delete}, "file_delete");
}