add rejection handlers

This commit is contained in:
LordMZTE 2021-06-24 16:22:27 +02:00
parent 6e3d6114ff
commit 0d8f70c2ab
4 changed files with 114 additions and 18 deletions

33
assets/404.html.tera Normal file
View File

@ -0,0 +1,33 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>brevo</title>
<style type="text/css" media="screen">
body {
background-color: #282a36;
color: #f8f8f2;
font-family: monospace;
}
#content {
width: 100vw;
height: 100vh;
align-items: center;
justify-content: center;
display: flex;
}
</style>
</head>
<body>
<div id="content">
<div>
<h1>404 Not Found</h1>
</div>
</div>
</body>
</html>

View File

@ -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<Brevo>) -> Result<Box<dyn Reply>, 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<Brevo>) -> Result<Box<dyn
}
}
pub async fn handle_reject(
brevo: Arc<Brevo>,
err: Rejection,
) -> Result<Box<dyn Reply>, 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<Brevo>,
err: Rejection,
) -> Result<Box<dyn Reply>, 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::<BrevoReject>() {
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::<BodyDeserializeError>().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<Brevo>) -> 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),

View File

@ -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;

View File

@ -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>(_: 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<Brevo>, id: &str) -> Result<String, Rejection> {