From 0d8f70c2abb0cedb06f141e8988bb8e7c4e54b26 Mon Sep 17 00:00:00 2001 From: LordMZTE Date: Thu, 24 Jun 2021 16:22:27 +0200 Subject: [PATCH] add rejection handlers --- assets/404.html.tera | 33 ++++++++++++++++++ src/handlers.rs | 82 ++++++++++++++++++++++++++++++++++++++------ src/main.rs | 7 ++-- src/util.rs | 10 +++--- 4 files changed, 114 insertions(+), 18 deletions(-) create mode 100644 assets/404.html.tera diff --git a/assets/404.html.tera b/assets/404.html.tera new file mode 100644 index 0000000..060efa2 --- /dev/null +++ b/assets/404.html.tera @@ -0,0 +1,33 @@ + + + + + + + brevo + + + + +
+
+

404 Not Found

+
+
+ + + diff --git a/src/handlers.rs b/src/handlers.rs index e18861a..e3848da 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -1,17 +1,17 @@ -use crate::util::gen_id; -use crate::util::make_link; -use crate::util::render_reject; +use crate::util::{gen_id, make_link, render_reject}; use serde::{Deserialize, Serialize}; use sqlx::Row; -use std::sync::Arc; +use std::{convert::Infallible, sync::Arc}; use tera::Context; use url::Url; -use warp::http::uri::InvalidUri; -use warp::redirect; use warp::{ - http::Uri, + body::BodyDeserializeError, + http::{uri::InvalidUri, Uri}, + redirect, reject::{self, Reject}, - reply, Rejection, Reply, + reply, + Rejection, + Reply, }; use crate::{sqlargs, util::sql_reject, Brevo}; @@ -19,7 +19,7 @@ use crate::{sqlargs, util::sql_reject, Brevo}; pub async fn index(brevo: Arc) -> Result, Rejection> { let rendered = brevo.tera.render("index.html", &Context::new()); match rendered { - Err(_) => Err(reject::custom(BrevoReject::RenderFail)), + Err(e) => Err(reject::custom(BrevoReject::RenderFail(e))), Ok(r) => Ok(Box::new(reply::html(r))), } } @@ -103,6 +103,68 @@ pub async fn submit(form_data: SubmitForm, brevo: Arc) -> Result, + err: Rejection, +) -> Result, Infallible> { + match try_handle_reject(brevo, err).await { + Ok(x) => Ok(x), + Err(e) => { + log::error!("Unrecoverable reply error occured! {:?}", e); + Ok(Box::new(reply::html("ERROR!! see logs"))) + }, + } +} + +pub async fn try_handle_reject( + brevo: Arc, + err: Rejection, +) -> Result, Rejection> { + if err.is_not_found() { + let rendered = brevo + .tera + .render("404.html", &Context::new()) + .map_err(render_reject)?; + + return Ok(Box::new(reply::html(rendered))); + } + + if let Some(rej) = err.find::() { + return match rej { + BrevoReject::SqlError(err) => { + log::error!("SQL error: {:?}", err); + Ok(Box::new(reply::html("SQL error! see logs."))) + }, + + BrevoReject::RenderFail(err) => { + log::error!("Template error: {:?}", err); + Ok(Box::new(reply::html( + "Failed to render template! see logs.", + ))) + }, + + BrevoReject::UrlParseError(err) => { + log::error!("URL parse error: {:?}", err); + Ok(Box::new(reply::html("Not a valid URL!"))) + }, + + BrevoReject::UriParseError(err) => { + log::error!("URI parse error: {:?}", err); + Ok(Box::new(reply::html("Not a valid URI!"))) + }, + }; + } + + if err.find::().is_some() { + return Ok(Box::new(reply::html( + "Invalid data! Did you enter a valid URI?", + ))); + } + + log::error!("unknown rejection: {:?}", err); + Ok(Box::new(reply::html("Found unknown rejection! see logs"))) +} + async fn make_table(brevo: Arc) -> Result<(), Rejection> { // can't parameterize VARCHAR len, but this should be safe sqlx::query(&format!( @@ -133,7 +195,7 @@ pub struct SubmitForm { // TODO: implement reject handerls #[derive(Debug)] pub enum BrevoReject { - RenderFail, + RenderFail(tera::Error), SqlError(sqlx::Error), UrlParseError(url::ParseError), UriParseError(InvalidUri), diff --git a/src/main.rs b/src/main.rs index b9803f4..9a74bb2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ -use tokio::sync::Mutex; use crate::config::Config; use anyhow::Context; use rand::{rngs::StdRng, SeedableRng}; @@ -6,6 +5,7 @@ use sqlx::MySqlPool; use std::sync::Arc; use structopt::StructOpt; use tera::Tera; +use tokio::sync::Mutex; use warp::Filter; mod config; @@ -35,6 +35,7 @@ async fn main() -> anyhow::Result<()> { tera.add_raw_templates(vec![ ("index.html", include_str!("../assets/index.html.tera")), ("success.html", include_str!("../assets/success.html.tera")), + ("404.html", include_str!("../assets/404.html.tera")), ]) .context("error adding templates to tera")?; @@ -47,6 +48,7 @@ async fn main() -> anyhow::Result<()> { let brevo_idx = Arc::clone(&brevo); let brevo_submit = Arc::clone(&brevo); let brevo_srv = Arc::clone(&brevo); + let brevo_reject = Arc::clone(&brevo); let routes = warp::get() .and( @@ -59,7 +61,8 @@ async fn main() -> anyhow::Result<()> { .or(warp::post() .and(warp::body::content_length_limit(1024 * 16)) .and(warp::body::form()) - .and_then(move |form_data| handlers::submit(form_data, Arc::clone(&brevo_submit)))); + .and_then(move |form_data| handlers::submit(form_data, Arc::clone(&brevo_submit)))) + .recover(move |err| handlers::handle_reject(Arc::clone(&brevo_reject), err)); warp::serve(routes).run(brevo_srv.config.bind_addr).await; diff --git a/src/util.rs b/src/util.rs index 4ff530c..2068f66 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,10 +1,8 @@ use std::sync::Arc; -use crate::handlers::BrevoReject; -use crate::Brevo; +use crate::{handlers::BrevoReject, Brevo}; use rand::seq::IteratorRandom; -use warp::reject; -use warp::Rejection; +use warp::{reject, Rejection}; #[macro_export] macro_rules! sqlargs { @@ -22,8 +20,8 @@ pub fn sql_reject(e: sqlx::Error) -> Rejection { reject::custom(BrevoReject::SqlError(e)) } -pub fn render_reject(_: T) -> Rejection { - reject::custom(BrevoReject::RenderFail) +pub fn render_reject(err: tera::Error) -> Rejection { + reject::custom(BrevoReject::RenderFail(err)) } pub fn make_link(brevo: Arc, id: &str) -> Result {