From 05073604a9a4145ce9c6666aedf8d4be442de163 Mon Sep 17 00:00:00 2001
From: Dmitry <b4tm4n@mail.ru>
Date: Sun, 20 Aug 2023 11:52:39 +0300
Subject: [PATCH] improve 404 catcher

---
 src/main.rs | 40 ++++++++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index fbf09b4..55be2ce 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -10,6 +10,7 @@ use rocket_dyn_templates::Template;
 use rand::distributions::Uniform;
 use rand::Rng;
 
+use std::collections::HashMap;
 use std::ops::Deref;
 use std::sync::Arc;
 
@@ -33,6 +34,19 @@ impl<T, E> ErrorEmpty for Result<T, E> {
     }
 }
 
+#[derive(Debug, Responder)]
+enum WebError {
+    #[response(status = 404)]
+    NotFound(Template),
+}
+
+impl WebError {
+    fn not_found() -> Self {
+        let context: HashMap<String, String> = HashMap::new();
+        WebError::NotFound(Template::render("404", context))
+    }
+}
+
 #[derive(Clone)]
 struct ArcTemplateData {
     value: Arc<tera::Value>,
@@ -85,9 +99,9 @@ async fn show_question_details(
     data: &AppState,
     cache: &TemplateCache,
     id: usize,
-) -> Template {
+) -> Option<Template> {
     if let Some(value) = cache.get(&id) {
-        return value.render(template_name);
+        return Some(value.render(template_name));
     }
 
     match get_question(&data.db, id).await {
@@ -102,13 +116,9 @@ async fn show_question_details(
             let result = value.render(template_name);
             cache.insert(id, value);
 
-            result
-        }
-        Err(_) => {
-            use std::collections::HashMap;
-            let context: HashMap<String, String> = HashMap::new();
-            Template::render("404", context)
+            Some(result)
         }
+        Err(_) => None,
     }
 }
 
@@ -117,12 +127,16 @@ async fn show_question(
     data: &State<AppState>,
     cache: &State<TemplateCache>,
     id: usize,
-) -> Template {
+) -> Option<Template> {
     show_question_details("question", data.inner(), cache.inner(), id).await
 }
 
 #[get("/q/<id>/a")]
-async fn show_answer(data: &State<AppState>, cache: &State<TemplateCache>, id: usize) -> Template {
+async fn show_answer(
+    data: &State<AppState>,
+    cache: &State<TemplateCache>,
+    id: usize,
+) -> Option<Template> {
     show_question_details("answer", data.inner(), cache.inner(), id).await
 }
 
@@ -143,10 +157,8 @@ fn index(data: &State<AppState>) -> Redirect {
 }
 
 #[catch(404)]
-fn not_found(_req: &rocket::Request) -> Template {
-    use std::collections::HashMap;
-    let context: HashMap<String, String> = HashMap::new();
-    Template::render("404", context)
+fn not_found(_req: &rocket::Request) -> WebError {
+    WebError::not_found()
 }
 
 #[launch]