use axum::{ body::Body, extract::State, http::{Response, StatusCode, header}, }; use crate::{ graph::Graph, router::{GlobalState, handlers}, }; pub(in crate::router::handlers) fn make( code: Option, message: Option<&str>, graph: &Graph, ) -> Response { let out_code = code.unwrap_or(500); let out_message = &message.unwrap_or("Unknown error"); let body = make_body(Some(out_code), Some(out_message), graph); handlers::raw::make_response( &body, out_code, &[(header::CONTENT_TYPE, "text/html")], ) } fn make_body( code: Option, message: Option<&str>, graph: &Graph, ) -> String { let mut context = tera::Context::default(); let out_code = code.unwrap_or(500); let out_message = &message.unwrap_or("Unknown error"); context.insert( "title", &StatusCode::from_u16(out_code) .unwrap_or(StatusCode::INTERNAL_SERVER_ERROR) .to_string(), ); context.insert("graph", graph); context.insert("message", out_message); context.insert("status_code", &out_code.to_string()); match handlers::template::render( "error", &context, Some(&format!( "Failed to render template for Error {out_code}: {out_message}" )) .cloned(), ) { Ok(rendered) => rendered.html, Err(error) => error.template.html, } } pub async fn not_found(State(state): State) -> Response { make( Some(404), Some("The page you tried to access could not be found."), &state.graph, ) } #[cfg(test)] mod tests { use axum::{extract::State, http::StatusCode}; use super::*; #[tokio::test] async fn not_found() { let state = State(GlobalState { graph: Graph::load(), }); let response = super::not_found(state).await; assert_eq!(response.status(), StatusCode::NOT_FOUND); } #[tokio::test] async fn internal_error() { let graph = Graph::load(); assert!(make(Some(201), None, &graph).status() == 201); assert!(make(Some(304), None, &graph).status() == 304); assert!(make(Some(418), None, &graph).status() == 418); assert!(make(Some(505), None, &graph).status() == 505); } #[test] fn custom_message() { let pattern = "sibPtt0mvHPWS9HQ0YBQfGu8cUs954LZ"; let body = make_body(Some(501), Some(pattern), &Graph::load()); assert!(body.contains(pattern)); assert!(!body.contains(&pattern.chars().rev().collect::())); } }