use crate::prelude::*; use axum::response::IntoResponse as _; use axum::{body::Body, extract::Path, http::Response, response::Redirect}; use crate::syntax::content; use crate::{syntax::serial::populate_graph, router::handlers, types::Node}; pub async fn node(Path(id): Path) -> Response { let graph = populate_graph(); let empty_node = Node::new(Some(format!("Could not find node ID {id}."))); let (node_match, exact) = graph.find_node(&id); let node = node_match.unwrap_or(empty_node.clone()); if !node.redirect.is_empty() { return Redirect::permanent( format!("/node/{}", node.redirect).as_str(), ) .into_response(); } if !exact { log!("Redirecting non-exact match to {}", node.id); return Redirect::permanent(format!("/node/{}", node.id).as_str()) .into_response(); } let mut context = tera::Context::default(); context.insert("node", &node); context.insert("text", &content::parse(&node.text, &graph.meta.config)); context.insert("incoming", &graph.incoming.get(&id)); context.insert("config", &graph.meta.config); let not_found = node == empty_node; handlers::template::by_filename( "node.html", &context, if not_found { 404 } else { 500 }, Some( format!( "Failed to generate page for node {} (ID {}).\n\ Node struct:
{:#?}
", node.title, id, node ) .to_owned(), ), not_found, ) } #[cfg(test)] mod tests { use axum::{ http::{HeaderName, StatusCode}, }; use super::*; #[tokio::test] async fn syntax() { let response = node(Path("Syntax".to_string())).await; assert_eq!(response.status(), StatusCode::OK); } #[tokio::test] async fn syntax_content_type() { let response = node(Path("Syntax".to_string())).await; assert!( response .headers() .get(HeaderName::from_static("content-type"),) .unwrap() .to_str() .unwrap() == "text/html" ); } #[tokio::test] async fn not_found() { let response = node(Path("InexistentNode".to_string())).await; assert_eq!(response.status(), StatusCode::NOT_FOUND); } #[tokio::test] async fn redirect() { let response = node(Path("syntax".to_string())).await; assert_eq!(response.status(), StatusCode::PERMANENT_REDIRECT); } }