summaryrefslogtreecommitdiff
path: root/src/server.rs
blob: 12ffedb4ebaf5338f81657de23dc46e03ac9aca8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use data;

use handlebars_iron::{HandlebarsEngine, MemorySource, Template};
use iron::headers::ContentType;
use iron::modifiers::Header;
use iron::{self, Iron, Plugin, Chain, Request, Response, IronResult, status};
use rusqlite::Connection;
use std::collections::BTreeMap;
use persistent::Write;
use handlebars_iron::handlebars::to_json;
use serde_json::Map;
use params;

#[derive(Debug)]
pub struct State {
    pub connection: Connection,
}
impl iron::typemap::Key for State {
    type Value = State;
}

fn make_renderer() -> HandlebarsEngine {
    let mut e = HandlebarsEngine::new();

    let mut templates = BTreeMap::new();
    templates.insert(
        "quotes".to_string(),
        include_str!("data/templates/quotes.hbs").to_string(),
    );
    templates.insert(
        "add".to_string(),
        include_str!("data/templates/add.hbs").to_string(),
    );

    e.add(Box::new(MemorySource(templates)));
    if let Err(r) = e.reload() {
        panic!("Error loading templates: {}", r)
    }
    e
}

fn quotes(r: &mut Request) -> IronResult<Response> {
    let mut result = Map::new();

    let (quote_id, ordering) = {
        let map = itry!(r.get_ref::<params::Params>());
        let quote_id = match map.get("id") {
            Some(&params::Value::String(ref id)) => Some(itry!(id.parse::<i64>())),
            _ => None,
        };
        let ordering = match map.get("order") {
            Some(&params::Value::String(ref ordering)) => ordering.clone(),
            _ => "".to_string(),
        };
	(quote_id, ordering)
    };

    let quotes = {
        let mu = r.get::<Write<State>>().unwrap();
        let state = mu.lock().unwrap();
        match quote_id {
            Some(id) => vec![data::get_quote(&state.connection, id)?],
            None => data::get_quotes(&state.connection, &ordering)?,
        }
    };
    result.insert("quotes".to_string(), to_json(&quotes));
    Ok(Response::with((
        status::Ok,
        Header(ContentType::html()),
        Template::new("quotes", result),
    )))
}

fn add_get(r: &mut Request) -> IronResult<Response> {
    Ok(Response::with((
        status::Ok,
        Header(ContentType::html()),
        Template::new("add", Map::new()),
    )))
}

pub fn serve(state: State, port: u16) {
    let router =
        router!(
        index: get "/" => quotes,
        add_get: get "/add.jsp" => add_get,
        quotes_jsp: get "/quotes.jsp" => quotes,
        view_quote: get "/view_quote" => quotes,
    );
    let mut chain = Chain::new(router);
    chain.link_after(make_renderer());
    chain.link(Write::<State>::both(state));
    let bind_address = format!("{}:{}", "::", port);
    let _server = Iron::new(chain).http(bind_address.as_str());
    info!("Serving on {}", bind_address);
}