diff --git a/src/handlers.rs b/src/handlers.rs new file mode 100644 index 000000000..446f59a4f --- /dev/null +++ b/src/handlers.rs @@ -0,0 +1,76 @@ +//! This module contains the implementation of converse's actix-web +//! HTTP handlers. +//! +//! Most handlers have an associated rendering function using one of +//! the tera templates stored in the `/templates` directory in the +//! project root. + +use tera; +use actix_web::*; +use models::*; +use db::*; +use actix::prelude::{Addr, Syn}; +use futures::Future; +use errors::{Result, ConverseError}; + +type ConverseResponse = Box>; + +/// Represents the state carried by the web server actors. +pub struct AppState { + /// Address of the database actor + pub db: Addr, + + /// Compiled templates + pub tera: tera::Tera, +} + +/// 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)) +} + +pub fn forum_index(state: State) -> ConverseResponse { + state.db.send(ListThreads) + .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()) + } + }) + .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()) + } + }) + .responder() +} diff --git a/src/main.rs b/src/main.rs index 3590975c8..8ce4e1082 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,74 +21,16 @@ extern crate serde; pub mod schema; pub mod models; pub mod db; +pub mod handlers; use actix::prelude::*; use actix_web::*; use actix_web::http::Method; - +use db::*; use diesel::pg::PgConnection; use diesel::r2d2::{ConnectionManager, Pool}; use std::env; -use db::*; -use futures::Future; -use models::*; - -/// Represents the state carried by the web server actors. -struct AppState { - /// Address of the database actor - db: Addr, - - /// Compiled templates - tera: tera::Tera, -} - -/// Really inefficient renderer example! -fn render_threads(tpl: &tera::Tera, threads: Vec) -> String { - let mut ctx = tera::Context::new(); - ctx.add("threads", &threads); - tpl.render("index.html", &ctx).expect("Oh no") -} - -fn forum_index(state: State) -> FutureResponse { - state.db.send(ListThreads) - .from_err() - .and_then(move |res| match res { - Ok(threads) => Ok(HttpResponse::Ok() - .content_type("text/html") - .body(render_threads(&state.tera, threads))), - Err(err) => { - error!("Error loading threads: {}", err); - Ok(HttpResponse::InternalServerError().into()) - } - }) - .responder() -} - -fn render_thread(tpl: &tera::Tera, thread: Thread, posts: Vec) -> HttpResponse { - let mut ctx = tera::Context::new(); - ctx.add("thread", &thread); - ctx.add("posts", &posts); - - let body = tpl.render("thread.html", &ctx).expect("Oh no"); - HttpResponse::Ok() - .content_type("text/html") - .body(body) -} - -fn forum_thread(state: State, thread_id: Path) - -> FutureResponse { - 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()) - } - }) - .responder() -} +use handlers::*; fn main() { env_logger::init();