#![forbid(unsafe_code)] #![warn(clippy::todo)] /// Database abstraction layer for Kittybox, allowing the CMS to work with any kind of database. pub mod database; pub mod frontend; pub mod tokenauth; pub mod media; pub mod micropub; pub mod indieauth; pub mod companion { use axum::{ extract::{Extension, Path}, response::IntoResponse }; #[derive(Debug, Clone, Copy)] struct Resource { data: &'static [u8], mime: &'static str } type ResourceTable = std::sync::Arc>; #[tracing::instrument] async fn map_to_static( Path(name): Path, Extension(resources): Extension ) -> impl IntoResponse { tracing::debug!("Searching for {} in the resource table...", name); if let Some(res) = resources.get(name.as_str()) { (axum::http::StatusCode::OK, [("Content-Type", res.mime)], res.data) } else { #[cfg(debug_assertions)] tracing::error!("Not found"); (axum::http::StatusCode::NOT_FOUND, [("Content-Type", "text/plain")], "Not found. Sorry.".as_bytes()) } } pub fn router() -> axum::Router { let resources = { let mut map = std::collections::HashMap::new(); macro_rules! register_resource { ($prefix:literal, ($filename:literal, $mime:literal)) => {{ map.insert($filename, Resource { data: include_bytes!(concat!($prefix, $filename)), mime: $mime }) }}; ($prefix:literal, ($filename:literal, $mime:literal), $( ($f:literal, $m:literal) ),+) => {{ register_resource!($prefix, ($filename, $mime)); register_resource!($prefix, $(($f, $m)),+); }}; } register_resource! { "../companion-lite/", ("index.html", "text/html; charset=\"utf-8\""), ("main.js", "text/javascript"), ("micropub_api.js", "text/javascript"), ("style.css", "text/css") }; std::sync::Arc::new(map) }; axum::Router::new() .route( "/:filename", axum::routing::get(map_to_static) .layer(Extension(resources)) ) } }