diff options
Diffstat (limited to 'src/companion.rs')
-rw-r--r-- | src/companion.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/companion.rs b/src/companion.rs new file mode 100644 index 0000000..debc266 --- /dev/null +++ b/src/companion.rs @@ -0,0 +1,84 @@ +use axum::{ + extract::{Extension, Path}, + response::{IntoResponse, Response}, +}; +use std::{collections::HashMap, sync::Arc}; + +#[derive(Debug, Clone, Copy)] +struct Resource { + data: &'static [u8], + mime: &'static str, +} + +impl IntoResponse for &Resource { + fn into_response(self) -> Response { + ( + axum::http::StatusCode::OK, + [("Content-Type", self.mime)], + self.data, + ) + .into_response() + } +} + +// TODO replace with the "phf" crate someday +type ResourceTable = Arc<HashMap<&'static str, Resource>>; + +#[tracing::instrument] +async fn map_to_static( + Path(name): Path<String>, + Extension(resources): Extension<ResourceTable>, +) -> Response { + tracing::debug!("Searching for {} in the resource table...", name); + match resources.get(name.as_str()) { + Some(res) => res.into_response(), + None => { + #[cfg(debug_assertions)] + tracing::error!("Not found"); + + ( + axum::http::StatusCode::NOT_FOUND, + [("Content-Type", "text/plain")], + "Not found. Sorry.".as_bytes(), + ) + .into_response() + } + } +} + +pub fn router<St: Clone + Send + Sync + 'static>() -> axum::Router<St> { + let resources: ResourceTable = { + let mut map = HashMap::new(); + + macro_rules! register_resource { + ($map:ident, $prefix:expr, ($filename:literal, $mime:literal)) => {{ + $map.insert($filename, Resource { + data: include_bytes!(concat!($prefix, $filename)), + mime: $mime + }) + }}; + ($map:ident, $prefix:expr, ($filename:literal, $mime:literal), $( ($f:literal, $m:literal) ),+) => {{ + register_resource!($map, $prefix, ($filename, $mime)); + register_resource!($map, $prefix, $(($f, $m)),+); + }}; + } + + register_resource! { + map, + concat!(env!("OUT_DIR"), "/", "companion", "/"), + ("index.html", "text/html; charset=\"utf-8\""), + ("main.js", "text/javascript"), + ("micropub_api.js", "text/javascript"), + ("indieauth.js", "text/javascript"), + ("base64.js", "text/javascript"), + ("style.css", "text/css") + }; + + Arc::new(map) + }; + + axum::Router::new().route( + "/{filename}", + axum::routing::get(map_to_static).layer(Extension(resources)), + ) +} |