From 1cce37446b3dbc558ffe82b1b1728279dec92175 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Wed, 11 Apr 2018 12:18:08 +0200 Subject: refactor(handlers): Use rendering actor for page renders This currently breaks error handling in page render flows. To fix it properly, the database actor should return failable futures instead of `Result` wrapped in a future. --- src/handlers.rs | 72 ++++++++++++++++++++++----------------------------------- todo.org | 5 +++- 2 files changed, 31 insertions(+), 46 deletions(-) diff --git a/src/handlers.rs b/src/handlers.rs index 3af8a8c40929..9732414b31cf 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -5,7 +5,7 @@ //! the tera templates stored in the `/templates` directory in the //! project root. -use actix::prelude::{Addr, Syn}; +use actix::prelude::*; use actix_web; use actix_web::*; use actix_web::middleware::{Started, Middleware, RequestSession}; @@ -15,9 +15,12 @@ use futures::Future; use models::*; use oidc::*; use tera; +use render::*; type ConverseResponse = Box>; +const HTML: &'static str = "text/html"; + /// Represents the state carried by the web server actors. pub struct AppState { /// Address of the database actor @@ -26,68 +29,47 @@ pub struct AppState { /// Address of the OIDC actor pub oidc: Addr, - /// Compiled templates - pub tera: tera::Tera, + /// Address of the rendering actor + pub renderer: Addr, } -/// This function renders an overview of threads into the default -/// thread list template. -fn render_threads(tpl: &tera::Tera, threads: Vec) -> Result { - let mut ctx = tera::Context::new(); - ctx.add("threads", &threads); - let body = tpl.render("index.html", &ctx)?; - Ok(HttpResponse::Ok().content_type("text/html").body(body)) -} +// impl AppState { +// fn render_ok(self, msg: M) -> ConverseResponse +// where M: Send + Message, Renderer: Handler { +// self.renderer.send(msg); +// unimplemented!() +// } +// } pub fn forum_index(state: State) -> ConverseResponse { state.db.send(ListThreads) + .and_then(move |res| state.renderer.send(IndexPage { threads: res.unwrap() })) .from_err() - .and_then(move |res| match res { - Ok(threads) => Ok(render_threads(&state.tera, threads)?), - Err(err) => { - error!("Error loading threads: {}", err); - Ok(HttpResponse::InternalServerError().into()) - } - }) + .map(|res| HttpResponse::Ok().content_type(HTML).body(res.unwrap())) .responder() } -/// This function renders a single forum thread into the default -/// thread view. -fn render_thread(tpl: &tera::Tera, thread: Thread, posts: Vec) - -> Result { - let mut ctx = tera::Context::new(); - ctx.add("thread", &thread); - ctx.add("posts", &posts); - - let body = tpl.render("thread.html", &ctx)?; - Ok(HttpResponse::Ok() - .content_type("text/html") - .body(body)) -} - /// This handler retrieves and displays a single forum thread. pub fn forum_thread(state: State, thread_id: Path) -> ConverseResponse { let id = thread_id.into_inner(); state.db.send(GetThread(id)) - .from_err() - .and_then(move |res| match res { - Ok((thread, posts)) => Ok(render_thread(&state.tera, thread, posts)?), - Err(err) => { - error!("Error loading thread {}: {}", id, err); - Ok(HttpResponse::InternalServerError().into()) - } + .and_then(move |res| { + let u = res.unwrap(); + state.renderer.send(ThreadPage { + thread: u.0, + posts: u.1, + }) }) + .from_err() + .map(|res| HttpResponse::Ok().content_type(HTML).body(res.unwrap())) .responder() } /// This handler presents the user with the "New Thread" form. -pub fn new_thread(state: State) -> Result { - let ctx = tera::Context::new(); - let body = state.tera.render("new-thread.html", &ctx)?; - Ok(HttpResponse::Ok() - .content_type("text/html") - .body(body)) +pub fn new_thread(state: State) -> ConverseResponse { + state.renderer.send(NewThreadPage).from_err() + .map(|res| HttpResponse::Ok().content_type(HTML).body(res.unwrap())) + .responder() } #[derive(Deserialize)] diff --git a/todo.org b/todo.org index af8fb223a2f3..63ad4ebb0645 100644 --- a/todo.org +++ b/todo.org @@ -1,4 +1,7 @@ +* DONE Pin *-versions in cargo.toml * TODO Configurable number of DB workers -* TODO Pin *-versions in cargo.toml * TODO Match certain types of Diesel errors (esp. for "not found") * TODO Sketch out categories vs. tags system +* TODO Markdown support +* TODO Quote button +* TODO Multiquote buttons -- cgit 1.4.1