tlaternet-webserver/src/main_pages.rs

98 lines
2.6 KiB
Rust

use actix_files::NamedFile;
use actix_web::{get, post, web, HttpRequest, HttpResponse, Responder};
use log::info;
use serde::Deserialize;
use crate::errors::UserError;
use crate::SharedData;
#[derive(Clone, Debug, Deserialize)]
pub(crate) struct Mail {
mail: String,
subject: String,
message: String,
}
#[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}")]
pub(crate) async fn template(
shared: web::Data<SharedData<'_>>,
req: HttpRequest,
) -> actix_web::Result<impl Responder> {
let path = req
.match_info()
.query("filename")
.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<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")]
pub(crate) async fn mail_post(
shared: web::Data<SharedData<'_>>,
form: web::Form<Mail>,
) -> actix_web::Result<impl Responder> {
info!("{:?}", form);
if shared.handlebars.has_template("mail") {
let body = shared
.handlebars
.render("mail", &())
.map_err(|_| UserError::InternalError)?;
Ok(HttpResponse::Ok().body(body))
} else {
Err(UserError::InternalError)?
}
}