...
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use actix_web::{error, Error, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
use tera::{self, Function, Result, Value};
|
||||
use tera::{self, Context, Function, Tera, Value};
|
||||
|
||||
// Export modules
|
||||
pub mod redis_service;
|
||||
@@ -7,6 +8,22 @@ pub mod redis_service;
|
||||
// Re-export for easier imports
|
||||
pub use redis_service::RedisCalendarService;
|
||||
|
||||
/// Error type for template rendering
|
||||
#[derive(Debug)]
|
||||
pub struct TemplateError {
|
||||
pub message: String,
|
||||
pub details: String,
|
||||
pub location: String,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for TemplateError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Template error in {}: {}", self.location, self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for TemplateError {}
|
||||
|
||||
/// Registers custom Tera functions
|
||||
pub fn register_tera_functions(tera: &mut tera::Tera) {
|
||||
tera.register_function("now", NowFunction);
|
||||
@@ -18,7 +35,7 @@ pub fn register_tera_functions(tera: &mut tera::Tera) {
|
||||
pub struct NowFunction;
|
||||
|
||||
impl Function for NowFunction {
|
||||
fn call(&self, args: &std::collections::HashMap<String, Value>) -> Result<Value> {
|
||||
fn call(&self, args: &std::collections::HashMap<String, Value>) -> tera::Result<Value> {
|
||||
let format = match args.get("format") {
|
||||
Some(val) => match val.as_str() {
|
||||
Some(s) => s,
|
||||
@@ -43,7 +60,7 @@ impl Function for NowFunction {
|
||||
pub struct FormatDateFunction;
|
||||
|
||||
impl Function for FormatDateFunction {
|
||||
fn call(&self, args: &std::collections::HashMap<String, Value>) -> Result<Value> {
|
||||
fn call(&self, args: &std::collections::HashMap<String, Value>) -> tera::Result<Value> {
|
||||
let timestamp = match args.get("timestamp") {
|
||||
Some(val) => match val.as_i64() {
|
||||
Some(ts) => ts,
|
||||
@@ -96,6 +113,50 @@ pub fn truncate_string(s: &str, max_length: usize) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Renders a template with error handling
|
||||
///
|
||||
/// This function attempts to render a template and handles any errors by rendering
|
||||
/// the error template with detailed error information.
|
||||
pub fn render_template(
|
||||
tmpl: &Tera,
|
||||
template_name: &str,
|
||||
ctx: &Context,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
match tmpl.render(template_name, ctx) {
|
||||
Ok(content) => Ok(HttpResponse::Ok().content_type("text/html").body(content)),
|
||||
Err(e) => {
|
||||
// Log the error
|
||||
log::error!("Template rendering error: {}", e);
|
||||
log::error!("Error details: {:?}", e);
|
||||
log::error!("Context: {:?}", ctx);
|
||||
|
||||
// Create a context for the error template
|
||||
let mut error_ctx = Context::new();
|
||||
error_ctx.insert("error", &format!("Template rendering error: {}", e));
|
||||
error_ctx.insert("error_details", &format!("{:?}", e));
|
||||
error_ctx.insert("error_location", &template_name);
|
||||
|
||||
// Try to render the error template
|
||||
match tmpl.render("error.html", &error_ctx) {
|
||||
Ok(error_page) => {
|
||||
// Return the error page with a 500 status code
|
||||
Ok(HttpResponse::InternalServerError()
|
||||
.content_type("text/html")
|
||||
.body(error_page))
|
||||
}
|
||||
Err(render_err) => {
|
||||
// If we can't render the error template, log it and return a basic error
|
||||
log::error!("Error rendering error template: {}", render_err);
|
||||
Err(error::ErrorInternalServerError(format!(
|
||||
"Template rendering error: {}. Failed to render error page: {}",
|
||||
e, render_err
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user