//! Branded 404/500 responses for in-handler error paths. //! //! The router `.fallback` renders a branded, session-aware error page, but //! errors raised *inside* a handler (missing thread/community, a bad UUID in the //! path, a DB failure) used to short-circuit with bare `(StatusCode, &str)` //! plaintext, unbranded and jarring. These helpers render the same //! `Error404Template`/`Error500Template` instead. //! //! They render a **session-less** shell (logged-out header), because the deep //! shared helpers that raise these errors don't carry the session. The only //! per-process value the templates need is `mnw_base_url` (all the chrome nav //! links), which is immutable config; it's stashed in a `OnceLock` at startup //! rather than threaded through ~80 call sites. The fallback handler still //! renders the fully session-aware page for unmatched routes. use std::sync::{Arc, OnceLock}; use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; use crate::templates::{Error404Template, Error500Template}; static MNW_BASE_URL: OnceLock> = OnceLock::new(); /// Record the MNW base URL for branded error pages. Called once at startup /// (and by the test harness); later calls are ignored. pub fn init(mnw_base_url: Arc) { let _ = MNW_BASE_URL.set(mnw_base_url); } fn base_url() -> Arc { MNW_BASE_URL.get().cloned().unwrap_or_else(|| Arc::from("")) } /// Branded 404 page (session-less). Use from shared handler helpers in place of /// a bare `(StatusCode::NOT_FOUND, "Not found")`. pub fn not_found() -> Response { ( StatusCode::NOT_FOUND, Error404Template { csrf_token: None, session_user: None, mnw_base_url: base_url(), }, ) .into_response() } /// Branded 500 page (session-less). Use from shared handler helpers in place of /// a bare `(StatusCode::INTERNAL_SERVER_ERROR, "Internal server error")`. pub fn internal_error() -> Response { ( StatusCode::INTERNAL_SERVER_ERROR, Error500Template { csrf_token: None, session_user: None, mnw_base_url: base_url(), }, ) .into_response() } /// A fully static, template-free branded 500. Used only when the Askama render /// itself fails; falling back to [`internal_error`] there would re-enter /// the template engine that's already broken. No interpolation, so it can never /// fail to produce output. pub fn internal_error_static() -> Response { const BODY: &str = "\n\ \ \ Something went wrong\ \
\

Something went wrong

\

This page couldn't be rendered. The error has been logged. Try again, or return to the forum home.

\
"; ( StatusCode::INTERNAL_SERVER_ERROR, axum::response::Html(BODY), ) .into_response() }