A little app to serve my photography from my personal website

improved error presentation

ericwood.org 7f1ba615 eb3e53b5

Waiting for spindle ...
+71 -4
+16
Cargo.lock
··· 2201 2201 ] 2202 2202 2203 2203 [[package]] 2204 + name = "html-escape" 2205 + version = "0.2.13" 2206 + source = "registry+https://github.com/rust-lang/crates.io-index" 2207 + checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" 2208 + dependencies = [ 2209 + "utf8-width", 2210 + ] 2211 + 2212 + [[package]] 2204 2213 name = "http" 2205 2214 version = "1.3.1" 2206 2215 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3063 3072 "chrono", 3064 3073 "comrak", 3065 3074 "dotenvy", 3075 + "html-escape", 3066 3076 "init-tracing-opentelemetry", 3067 3077 "minijinja", 3068 3078 "minijinja-autoreload", ··· 4627 4637 version = "2.1.3" 4628 4638 source = "registry+https://github.com/rust-lang/crates.io-index" 4629 4639 checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" 4640 + 4641 + [[package]] 4642 + name = "utf8-width" 4643 + version = "0.1.8" 4644 + source = "registry+https://github.com/rust-lang/crates.io-index" 4645 + checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091" 4630 4646 4631 4647 [[package]] 4632 4648 name = "utf8_iter"
+2 -1
Cargo.toml
··· 15 15 "tracing_subscriber_ext", 16 16 "metrics", 17 17 ] } 18 - minijinja = { version = "2.12.0", features = ["loader"] } 18 + minijinja = { version = "2.12.0", features = ["loader", "debug"] } 19 19 minijinja-autoreload = "2.12.0" 20 20 serde = "1.0.228" 21 21 serde_html_form = "0.2.8" ··· 32 32 arborium = { version = "2.3.2", features = ["all-languages"] } 33 33 slug = "0.1.6" 34 34 regex = "1.12.2" 35 + html-escape = "0.2.13"
+45 -1
src/app_error.rs
··· 45 45 let body = if status_code == StatusCode::INTERNAL_SERVER_ERROR && !is_dev { 46 46 "internal server error".to_string() 47 47 } else { 48 - self.to_string() 48 + let body = if let Self::Anyhow(e) = &self 49 + && let Some(template_error) = e.downcast_ref::<minijinja::Error>() 50 + { 51 + let debug = template_error.display_debug_info().to_string(); 52 + let kind = template_error.kind(); 53 + let detail = template_error.detail().unwrap_or_default(); 54 + let name = template_error.name().unwrap_or_default(); 55 + let line = template_error.line().unwrap_or_default(); 56 + 57 + format!("{kind}: {detail}\n{name}:{line}\n{}", debug) 58 + } else { 59 + format!("{:#?}", self) 60 + }; 61 + 62 + render_error(body) 49 63 }; 50 64 51 65 (self.status_code(), Html(body)).into_response() 52 66 } 53 67 } 68 + 69 + fn render_error(body: String) -> String { 70 + let style = r#" 71 + body { 72 + padding: 30px; 73 + font-family: sans-serif; 74 + } 75 + 76 + pre { 77 + background-color: #eee; 78 + padding: 20px; 79 + border-radius: 6px; 80 + } 81 + "#; 82 + 83 + format!( 84 + r#" 85 + <html> 86 + <head> 87 + <style type="text/css">{style}</style> 88 + </head> 89 + <body> 90 + <h1>Error:</h1> 91 + <pre><code>{}</code></pre> 92 + </body> 93 + </html> 94 + "#, 95 + html_escape::encode_text(&body) 96 + ) 97 + }
+8 -2
src/templates.rs
··· 15 15 pub fn load_templates_dyn(config: &Config) -> AutoReloader { 16 16 let should_autoreload = config.auto_reload_templates; 17 17 let blog_posts_path_str = config.blog_posts_path.clone(); 18 + let is_prod = config.is_prod(); 18 19 19 20 AutoReloader::new(move |notifier| { 20 21 let mut env = Environment::new(); 21 22 env.set_loader(loader); 23 + env.set_debug(!is_prod); 22 24 23 25 notifier.set_fast_reload(true); 24 26 ··· 92 94 Ok(Some(template)) 93 95 } 94 96 95 - pub fn render<S>(reloader: &AutoReloader, name: &str, context: S) -> anyhow::Result<String> 97 + pub fn render<S>( 98 + reloader: &AutoReloader, 99 + name: &str, 100 + context: S, 101 + ) -> Result<String, minijinja::Error> 96 102 where 97 103 S: Serialize, 98 104 { 99 105 let template_env = reloader.acquire_env()?; 100 106 let template = template_env.get_template(name)?; 101 - Ok(template.render(context)?) 107 + template.render(context) 102 108 } 103 109 104 110 fn url_escape(input: String) -> String {