move handlebar data out of state struct

This commit is contained in:
Edward Shen 2019-12-26 16:17:05 -05:00
parent b59cb4f9e3
commit 062c8f5a2e
Signed by: edward
GPG key ID: F350507060ED6C90
2 changed files with 46 additions and 15 deletions

View file

@ -64,7 +64,6 @@ pub struct State {
groups: Vec<RouteGroup>, groups: Vec<RouteGroup>,
/// Cached, flattened mapping of all routes and their destinations. /// Cached, flattened mapping of all routes and their destinations.
routes: HashMap<String, String>, routes: HashMap<String, String>,
renderer: Handlebars,
} }
#[actix_rt::main] #[actix_rt::main]
@ -83,13 +82,11 @@ async fn main() -> Result<(), BunBunError> {
// config has default location provided, unwrapping is fine. // config has default location provided, unwrapping is fine.
let conf_file_location = String::from(matches.value_of("config").unwrap()); let conf_file_location = String::from(matches.value_of("config").unwrap());
let conf = read_config(&conf_file_location)?; let conf = read_config(&conf_file_location)?;
let renderer = compile_templates();
let state = Arc::from(RwLock::new(State { let state = Arc::from(RwLock::new(State {
public_address: conf.public_address, public_address: conf.public_address,
default_route: conf.default_route, default_route: conf.default_route,
routes: cache_routes(&conf.groups), routes: cache_routes(&conf.groups),
groups: conf.groups, groups: conf.groups,
renderer,
})); }));
// Daemonize after trying to read from config and before watching; allow user // Daemonize after trying to read from config and before watching; allow user
@ -106,6 +103,7 @@ async fn main() -> Result<(), BunBunError> {
HttpServer::new(move || { HttpServer::new(move || {
App::new() App::new()
.data(state.clone()) .data(state.clone())
.app_data(compile_templates())
.wrap(Logger::default()) .wrap(Logger::default())
.service(routes::hop) .service(routes::hop)
.service(routes::list) .service(routes::list)
@ -195,6 +193,9 @@ fn read_config(config_file_path: &str) -> Result<Config, BunBunError> {
Ok(serde_yaml::from_str(&config_str)?) Ok(serde_yaml::from_str(&config_str)?)
} }
/// Generates a hashmap of routes from the data structure created by the config
/// file. This should improve runtime performance and is a better solution than
/// just iterating over the config object for every hop resolution.
fn cache_routes(groups: &[RouteGroup]) -> HashMap<String, String> { fn cache_routes(groups: &[RouteGroup]) -> HashMap<String, String> {
let mut mapping = HashMap::new(); let mut mapping = HashMap::new();
for group in groups { for group in groups {
@ -233,6 +234,15 @@ fn compile_templates() -> Handlebars {
handlebars handlebars
} }
/// Starts the watch on a file, if possible. This will only return an Error if
/// the notify library (used by Hotwatch) fails to initialize, which is
/// considered to be a more serve error as it may be indicative of a low-level
/// problem. If a watch was unsuccessfully obtained (the most common is due to
/// the file not existing), then this will simply warn before returning a watch
/// object.
///
/// This watch object should be kept in scope as dropping it releases all
/// watches.
fn start_watch( fn start_watch(
state: Arc<RwLock<State>>, state: Arc<RwLock<State>>,
config_file_path: String, config_file_path: String,
@ -267,6 +277,7 @@ fn start_watch(
"Couldn't watch {}: {}. Changes to this file won't be seen!", "Couldn't watch {}: {}. Changes to this file won't be seen!",
&config_file_path, e &config_file_path, e
), ),
}; }
Ok(watch) Ok(watch)
} }

View file

@ -3,7 +3,8 @@ use crate::State;
use actix_web::get; use actix_web::get;
use actix_web::http::header; use actix_web::http::header;
use actix_web::web::{Data, Query}; use actix_web::web::{Data, Query};
use actix_web::{HttpResponse, Responder}; use actix_web::{HttpRequest, HttpResponse, Responder};
use handlebars::Handlebars;
use itertools::Itertools; use itertools::Itertools;
use log::debug; use log::debug;
use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS}; use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS};
@ -21,9 +22,18 @@ const FRAGMENT_ENCODE_SET: &AsciiSet = &CONTROLS
.add(b'+'); .add(b'+');
#[get("/ls")] #[get("/ls")]
pub async fn list(data: Data<Arc<RwLock<State>>>) -> impl Responder { pub async fn list(
data: Data<Arc<RwLock<State>>>,
req: HttpRequest,
) -> impl Responder {
let data = data.read().unwrap(); let data = data.read().unwrap();
HttpResponse::Ok().body(data.renderer.render("list", &data.groups).unwrap()) HttpResponse::Ok().body(
req
.app_data::<Handlebars>()
.unwrap()
.render("list", &data.groups)
.unwrap(),
)
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -34,6 +44,7 @@ pub struct SearchQuery {
#[get("/hop")] #[get("/hop")]
pub async fn hop( pub async fn hop(
data: Data<Arc<RwLock<State>>>, data: Data<Arc<RwLock<State>>>,
req: HttpRequest,
query: Query<SearchQuery>, query: Query<SearchQuery>,
) -> impl Responder { ) -> impl Responder {
let data = data.read().unwrap(); let data = data.read().unwrap();
@ -42,8 +53,9 @@ pub async fn hop(
(Some(path), args) => HttpResponse::Found() (Some(path), args) => HttpResponse::Found()
.header( .header(
header::LOCATION, header::LOCATION,
data req
.renderer .app_data::<Handlebars>()
.unwrap()
.render_template( .render_template(
&path, &path,
&template_args::query( &template_args::query(
@ -109,11 +121,15 @@ fn resolve_hop(
} }
#[get("/")] #[get("/")]
pub async fn index(data: Data<Arc<RwLock<State>>>) -> impl Responder { pub async fn index(
data: Data<Arc<RwLock<State>>>,
req: HttpRequest,
) -> impl Responder {
let data = data.read().unwrap(); let data = data.read().unwrap();
HttpResponse::Ok().body( HttpResponse::Ok().body(
data req
.renderer .app_data::<Handlebars>()
.unwrap()
.render( .render(
"index", "index",
&template_args::hostname(data.public_address.clone()), &template_args::hostname(data.public_address.clone()),
@ -123,7 +139,10 @@ pub async fn index(data: Data<Arc<RwLock<State>>>) -> impl Responder {
} }
#[get("/bunbunsearch.xml")] #[get("/bunbunsearch.xml")]
pub async fn opensearch(data: Data<Arc<RwLock<State>>>) -> impl Responder { pub async fn opensearch(
data: Data<Arc<RwLock<State>>>,
req: HttpRequest,
) -> impl Responder {
let data = data.read().unwrap(); let data = data.read().unwrap();
HttpResponse::Ok() HttpResponse::Ok()
.header( .header(
@ -131,8 +150,9 @@ pub async fn opensearch(data: Data<Arc<RwLock<State>>>) -> impl Responder {
"application/opensearchdescription+xml", "application/opensearchdescription+xml",
) )
.body( .body(
data req
.renderer .app_data::<Handlebars>()
.unwrap()
.render( .render(
"opensearch", "opensearch",
&template_args::hostname(data.public_address.clone()), &template_args::hostname(data.public_address.clone()),