Use actix-web 4.2.1 features to clean up resource handling
This commit is contained in:
parent
9035cf5419
commit
a960bf4b27
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -44,9 +44,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "actix-http"
|
name = "actix-http"
|
||||||
version = "3.2.1"
|
version = "3.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6f9ffb6db08c1c3a1f4aef540f1a63193adc73c4fbd40b75a95fc8c5258f6e51"
|
checksum = "0c83abf9903e1f0ad9973cc4f7b9767fd5a03a583f51a5b7a339e07987cd2724"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-codec",
|
"actix-codec",
|
||||||
"actix-rt",
|
"actix-rt",
|
||||||
|
@ -154,9 +154,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "actix-web"
|
name = "actix-web"
|
||||||
version = "4.1.0"
|
version = "4.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a27e8fe9ba4ae613c21f677c2cfaf0696c3744030c6f485b34634e502d6bb379"
|
checksum = "d48f7b6534e06c7bfc72ee91db7917d4af6afe23e7d223b51e68fffbb21e96b9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-codec",
|
"actix-codec",
|
||||||
"actix-http",
|
"actix-http",
|
||||||
|
@ -176,6 +176,7 @@ dependencies = [
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"http",
|
||||||
"itoa",
|
"itoa",
|
||||||
"language-tags",
|
"language-tags",
|
||||||
"log",
|
"log",
|
||||||
|
@ -194,9 +195,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "actix-web-codegen"
|
name = "actix-web-codegen"
|
||||||
version = "4.0.1"
|
version = "4.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f270541caec49c15673b0af0e9a00143421ad4f118d2df7edcb68b627632f56"
|
checksum = "1fa9362663c8643d67b2d5eafba49e4cb2c8a053a29ed00a0bea121f17c76b13"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-router",
|
"actix-router",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-files = "0.6.2"
|
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"] }
|
clap = { version = "3.2.17", features = ["derive"] }
|
||||||
derive_more = "0.99.17"
|
derive_more = "0.99.17"
|
||||||
env_logger = "0.9.0"
|
env_logger = "0.9.0"
|
||||||
|
|
|
@ -7,7 +7,7 @@ use actix_web::{web, HttpResponse, ResponseError};
|
||||||
use derive_more::{Display, Error};
|
use derive_more::{Display, Error};
|
||||||
|
|
||||||
use super::SharedData;
|
use super::SharedData;
|
||||||
use crate::template_utils::{ErrorMessage, TemplateArgs};
|
use crate::template_utils::{render_template, ErrorMessage, TemplateArgs};
|
||||||
|
|
||||||
#[derive(Debug, Display, Error)]
|
#[derive(Debug, Display, Error)]
|
||||||
pub enum UserError {
|
pub enum UserError {
|
||||||
|
@ -56,8 +56,7 @@ pub fn generic_error<B>(
|
||||||
.error_page(ErrorMessage::new(message, status_code.as_u16()))
|
.error_page(ErrorMessage::new(message, status_code.as_u16()))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let body = handlebars
|
let body = render_template(handlebars, "error", &args)
|
||||||
.render("error", &args)
|
|
||||||
.map_err(|_| UserError::InternalError)?;
|
.map_err(|_| UserError::InternalError)?;
|
||||||
|
|
||||||
HttpResponse::build(res.status())
|
HttpResponse::build(res.status())
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use actix_files::Files;
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
http::{Method, StatusCode},
|
http::{Method, StatusCode},
|
||||||
middleware::{self, ErrorHandlers},
|
middleware::{self, ErrorHandlers},
|
||||||
|
@ -15,7 +16,7 @@ mod main_pages;
|
||||||
mod template_utils;
|
mod template_utils;
|
||||||
|
|
||||||
use errors::generic_error;
|
use errors::generic_error;
|
||||||
use main_pages::{mail_post, static_file, template, template_index};
|
use main_pages::{mail_post, template};
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
struct Config {
|
struct Config {
|
||||||
|
@ -66,9 +67,8 @@ async fn main() -> std::io::Result<()> {
|
||||||
)
|
)
|
||||||
.app_data(shared_data.clone())
|
.app_data(shared_data.clone())
|
||||||
.service(template)
|
.service(template)
|
||||||
.service(static_file)
|
|
||||||
.service(template_index)
|
|
||||||
.service(mail_post)
|
.service(mail_post)
|
||||||
|
.service(Files::new("/", &config.template_directory))
|
||||||
.default_service(web::route().method(Method::GET))
|
.default_service(web::route().method(Method::GET))
|
||||||
})
|
})
|
||||||
.bind(config.address)?
|
.bind(config.address)?
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
use actix_files::NamedFile;
|
use actix_web::{post, routes, web, HttpRequest, HttpResponse, Responder};
|
||||||
use actix_web::{get, post, web, HttpRequest, HttpResponse, Responder};
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::errors::UserError;
|
use crate::template_utils::{render_template, Flash, FlashType, TemplateArgs};
|
||||||
use crate::template_utils::TemplateArgs;
|
|
||||||
use crate::template_utils::{Flash, FlashType};
|
|
||||||
use crate::SharedData;
|
use crate::SharedData;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
@ -15,69 +12,22 @@ pub(crate) struct Mail {
|
||||||
message: String,
|
message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[routes]
|
||||||
#[get(r"/")]
|
#[get(r"/")]
|
||||||
pub(crate) async fn template_index(
|
|
||||||
shared: web::Data<SharedData<'_>>,
|
|
||||||
) -> actix_web::Result<impl Responder> {
|
|
||||||
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}")]
|
#[get(r"/{filename:.*\.html}")]
|
||||||
pub(crate) async fn template(
|
pub(crate) async fn template(
|
||||||
shared: web::Data<SharedData<'_>>,
|
shared: web::Data<SharedData<'_>>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let path = req
|
let path = match req.match_info().query("filename") {
|
||||||
.match_info()
|
"" => "index",
|
||||||
.query("filename")
|
other => other
|
||||||
.strip_suffix(".html")
|
.strip_suffix(".html")
|
||||||
.expect("only paths with this suffix should get here");
|
.expect("only paths with this suffix should get here"),
|
||||||
|
};
|
||||||
|
|
||||||
if shared.handlebars.has_template(path) {
|
render_template(&shared.handlebars, path, &TemplateArgs::default())
|
||||||
let body = shared
|
.map(|body| HttpResponse::Ok().body(body))
|
||||||
.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<SharedData<'_>>,
|
|
||||||
req: HttpRequest,
|
|
||||||
) -> actix_web::Result<impl Responder> {
|
|
||||||
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)?,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/mail.html")]
|
#[post("/mail.html")]
|
||||||
|
@ -91,13 +41,5 @@ pub(crate) async fn mail_post(
|
||||||
.flash(Flash::new("Mail successfully sent!", FlashType::Success))
|
.flash(Flash::new("Mail successfully sent!", FlashType::Success))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if shared.handlebars.has_template("mail") {
|
render_template(&shared.handlebars, "mail", &args).map(|body| HttpResponse::Ok().body(body))
|
||||||
let body = shared
|
|
||||||
.handlebars
|
|
||||||
.render("mail", &args)
|
|
||||||
.map_err(|_| UserError::InternalError)?;
|
|
||||||
Ok(HttpResponse::Ok().body(body))
|
|
||||||
} else {
|
|
||||||
Err(UserError::InternalError)?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,23 @@
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::errors::UserError;
|
||||||
|
|
||||||
|
pub fn render_template(
|
||||||
|
handlebars: &handlebars::Handlebars,
|
||||||
|
name: &str,
|
||||||
|
args: &TemplateArgs,
|
||||||
|
) -> actix_web::Result<String> {
|
||||||
|
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. */
|
/** All arguments that can be given to a template. */
|
||||||
#[derive(Serialize)]
|
#[derive(Default, Serialize)]
|
||||||
pub struct TemplateArgs {
|
pub struct TemplateArgs {
|
||||||
flash: Option<Flash>,
|
flash: Option<Flash>,
|
||||||
error: Option<ErrorMessage>,
|
error: Option<ErrorMessage>,
|
||||||
|
|
Loading…
Reference in a new issue