#![allow(dead_code)] use std::net::SocketAddr; use std::path::PathBuf; use actix_files::Files; use actix_web::{ http::{Method, StatusCode}, middleware::{self, ErrorHandlers}, web, App, HttpServer, }; use clap::Parser; use handlebars::Handlebars; mod errors; mod main_pages; mod template_utils; use errors::generic_error; use main_pages::{mail_post, template}; #[derive(Parser, Debug, Clone)] struct Config { #[clap(long, value_parser)] /// The directory from which to serve static content and /// handlebars templates template_directory: PathBuf, #[clap(long, default_value = "127.0.0.1:8000", value_parser)] /// The address on which to listen address: SocketAddr, #[clap(long, action)] /// Whether to start the server in dev mode; this enables some /// nice handlebars features that are not intended for production dev_mode: bool, } #[derive(Debug)] struct SharedData<'a> { handlebars: Handlebars<'a>, config: Config, } #[actix_web::main] async fn main() -> std::io::Result<()> { let mut config = Config::parse(); config.template_directory = config.template_directory.canonicalize()?; env_logger::init(); let mut handlebars = Handlebars::new(); handlebars .register_templates_directory(".html", config.template_directory.clone()) .expect("templates should compile correctly"); handlebars.set_dev_mode(config.dev_mode); let shared_data = web::Data::new(SharedData { handlebars, config: config.clone(), }); HttpServer::new(move || { App::new() .wrap(middleware::NormalizePath::trim()) // TODO(tlater): When actix-web 4.3 releases, this can be improved a // lot because of this PR: // // https://github.com/actix/actix-web/pull/2784 .wrap( ErrorHandlers::new() .handler(StatusCode::NOT_FOUND, generic_error) .handler(StatusCode::INTERNAL_SERVER_ERROR, generic_error), ) .app_data(shared_data.clone()) .service(template) .service(mail_post) .service(Files::new("/", &config.template_directory)) .default_service(web::route().method(Method::GET)) }) .bind(config.address)? .run() .await }