use handlebars::Handlebars; use serde::Serialize; use std::sync::Arc; use warp::{http::Uri, Filter, Rejection}; #[tokio::main] async fn main() -> Result<(), Box> { // Build template registry let mut hbs = Handlebars::new(); hbs.register_template_file("base", "templates/base.hbs")?; hbs.register_template_file("index", "templates/index.hbs")?; hbs.register_template_file("policies", "templates/policies.hbs")?; hbs.register_template_file("about", "templates/about.hbs")?; let hbs = Arc::new(hbs); // Build routes let routes = index_filter(hbs.clone()) .or(template_filter(hbs.clone())) .or(redirect_static_ext()) .or(evals_list()) .or(warp::fs::dir("static")); // Start server warp::serve(routes).run(([127, 0, 0, 1], 8080)).await; // Done Ok(()) } fn index_filter( hbs: Arc>, ) -> impl Filter + Clone { warp::get() .and(warp::path::end()) .map(move || render("index", hbs.clone(), "")) } fn template_filter( hbs: Arc>, ) -> impl Filter + Clone { warp::path!(String).and_then(move |name: String| { let hbs = hbs.clone(); async move { if hbs.has_template(&name) { Ok(render(&name, hbs, "")) } else { Err(warp::reject::not_found()) } } }) } fn redirect_static_ext() -> impl Filter + Clone { warp::path!(String).and_then(move |path: String| async move { if let Some(prefix) = path.strip_suffix(".php") { return Ok(warp::redirect( prefix .parse::() .unwrap_or_else(|_| Uri::from_static("/")), )); } if let Some(prefix) = path.strip_suffix(".html") { return Ok(warp::redirect( prefix .parse::() .unwrap_or_else(|_| Uri::from_static("/")), )); } Err(warp::reject::not_found()) }) } fn evals_list() -> impl Filter + Clone { warp::get() .and(warp::path("evals")) .and(warp::path::end()) .map(|| "evals here") } fn render(template: &str, hbs: Arc, value: T) -> impl warp::Reply where T: Serialize, { let render = hbs .render(template, &value) .unwrap_or_else(|err| err.to_string()); warp::reply::html(render) }