From a960bf4b27459258a5063da5999641cd68a07477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Fri, 16 Sep 2022 17:16:12 +0100 Subject: [PATCH] Use actix-web 4.2.1 features to clean up resource handling --- Cargo.lock | 13 +++---- Cargo.toml | 2 +- src/errors.rs | 5 ++- src/main.rs | 6 ++-- src/main_pages.rs | 82 +++++++------------------------------------ src/template_utils.rs | 18 +++++++++- 6 files changed, 42 insertions(+), 84 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a5cb11..e5fde96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,9 +44,9 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.2.1" +version = "3.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f9ffb6db08c1c3a1f4aef540f1a63193adc73c4fbd40b75a95fc8c5258f6e51" +checksum = "0c83abf9903e1f0ad9973cc4f7b9767fd5a03a583f51a5b7a339e07987cd2724" dependencies = [ "actix-codec", "actix-rt", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.1.0" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27e8fe9ba4ae613c21f677c2cfaf0696c3744030c6f485b34634e502d6bb379" +checksum = "d48f7b6534e06c7bfc72ee91db7917d4af6afe23e7d223b51e68fffbb21e96b9" dependencies = [ "actix-codec", "actix-http", @@ -176,6 +176,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", + "http", "itoa", "language-tags", "log", @@ -194,9 +195,9 @@ dependencies = [ [[package]] name = "actix-web-codegen" -version = "4.0.1" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f270541caec49c15673b0af0e9a00143421ad4f118d2df7edcb68b627632f56" +checksum = "1fa9362663c8643d67b2d5eafba49e4cb2c8a053a29ed00a0bea121f17c76b13" dependencies = [ "actix-router", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 1ad1857..14a5f17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] actix-files = "0.6.2" -actix-web = "4.1.0" +actix-web = { version = "4.2.1", features = ["macros"] } clap = { version = "3.2.17", features = ["derive"] } derive_more = "0.99.17" env_logger = "0.9.0" diff --git a/src/errors.rs b/src/errors.rs index 6d02d1b..9770c00 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -7,7 +7,7 @@ use actix_web::{web, HttpResponse, ResponseError}; use derive_more::{Display, Error}; use super::SharedData; -use crate::template_utils::{ErrorMessage, TemplateArgs}; +use crate::template_utils::{render_template, ErrorMessage, TemplateArgs}; #[derive(Debug, Display, Error)] pub enum UserError { @@ -56,8 +56,7 @@ pub fn generic_error( .error_page(ErrorMessage::new(message, status_code.as_u16())) .build(); - let body = handlebars - .render("error", &args) + let body = render_template(handlebars, "error", &args) .map_err(|_| UserError::InternalError)?; HttpResponse::build(res.status()) diff --git a/src/main.rs b/src/main.rs index 94327fb..df73a34 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use std::net::SocketAddr; use std::path::PathBuf; +use actix_files::Files; use actix_web::{ http::{Method, StatusCode}, middleware::{self, ErrorHandlers}, @@ -15,7 +16,7 @@ mod main_pages; mod template_utils; use errors::generic_error; -use main_pages::{mail_post, static_file, template, template_index}; +use main_pages::{mail_post, template}; #[derive(Parser, Debug, Clone)] struct Config { @@ -66,9 +67,8 @@ async fn main() -> std::io::Result<()> { ) .app_data(shared_data.clone()) .service(template) - .service(static_file) - .service(template_index) .service(mail_post) + .service(Files::new("/", &config.template_directory)) .default_service(web::route().method(Method::GET)) }) .bind(config.address)? diff --git a/src/main_pages.rs b/src/main_pages.rs index 3f247a7..ab77276 100644 --- a/src/main_pages.rs +++ b/src/main_pages.rs @@ -1,11 +1,8 @@ -use actix_files::NamedFile; -use actix_web::{get, post, web, HttpRequest, HttpResponse, Responder}; +use actix_web::{post, routes, web, HttpRequest, HttpResponse, Responder}; use log::info; use serde::Deserialize; -use crate::errors::UserError; -use crate::template_utils::TemplateArgs; -use crate::template_utils::{Flash, FlashType}; +use crate::template_utils::{render_template, Flash, FlashType, TemplateArgs}; use crate::SharedData; #[derive(Clone, Debug, Deserialize)] @@ -15,69 +12,22 @@ pub(crate) struct Mail { message: String, } +#[routes] #[get(r"/")] -pub(crate) async fn template_index( - shared: web::Data>, -) -> actix_web::Result { - if shared.handlebars.has_template("index") { - let body = shared - .handlebars - .render("index", &()) - .map_err(|_| UserError::InternalError)?; - Ok(HttpResponse::Ok().body(body)) - } else { - Err(UserError::NotFound)? - } -} - #[get(r"/{filename:.*\.html}")] pub(crate) async fn template( shared: web::Data>, req: HttpRequest, ) -> actix_web::Result { - let path = req - .match_info() - .query("filename") - .strip_suffix(".html") - .expect("only paths with this suffix should get here"); + let path = match req.match_info().query("filename") { + "" => "index", + other => other + .strip_suffix(".html") + .expect("only paths with this suffix should get here"), + }; - if shared.handlebars.has_template(path) { - let body = shared - .handlebars - .render(path, &()) - .map_err(|_| UserError::InternalError)?; - Ok(HttpResponse::Ok().body(body)) - } else { - Err(UserError::NotFound)? - } -} - -#[get("/{filename:.*[^/]+}")] -pub(crate) async fn static_file( - shared: web::Data>, - req: HttpRequest, -) -> actix_web::Result { - let requested = req.match_info().query("filename"); - - match shared - .config - .template_directory - .join(requested) - .canonicalize() - { - // We only want to serve paths that are both valid *and* in - // the template directory. - // - // i.e., don't serve up /etc/passwd - Ok(path) if path.starts_with(&shared.config.template_directory) => { - let file = NamedFile::open_async(path) - .await - .map_err(|_| UserError::NotFound)?; - Ok(file.use_last_modified(false).respond_to(&req)) - } - // Any other cases should 404 - _ => Err(UserError::NotFound)?, - } + render_template(&shared.handlebars, path, &TemplateArgs::default()) + .map(|body| HttpResponse::Ok().body(body)) } #[post("/mail.html")] @@ -91,13 +41,5 @@ pub(crate) async fn mail_post( .flash(Flash::new("Mail successfully sent!", FlashType::Success)) .build(); - if shared.handlebars.has_template("mail") { - let body = shared - .handlebars - .render("mail", &args) - .map_err(|_| UserError::InternalError)?; - Ok(HttpResponse::Ok().body(body)) - } else { - Err(UserError::InternalError)? - } + render_template(&shared.handlebars, "mail", &args).map(|body| HttpResponse::Ok().body(body)) } diff --git a/src/template_utils.rs b/src/template_utils.rs index 84be858..d80b82c 100644 --- a/src/template_utils.rs +++ b/src/template_utils.rs @@ -1,7 +1,23 @@ use serde::Serialize; +use crate::errors::UserError; + +pub fn render_template( + handlebars: &handlebars::Handlebars, + name: &str, + args: &TemplateArgs, +) -> actix_web::Result { + if handlebars.has_template(name) { + Ok(handlebars + .render(name, args) + .map_err(|_| UserError::InternalError)?) + } else { + Err(UserError::NotFound)? + } +} + /** All arguments that can be given to a template. */ -#[derive(Serialize)] +#[derive(Default, Serialize)] pub struct TemplateArgs { flash: Option, error: Option,