about summary refs log tree commit diff
path: root/src/companion.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/companion.rs')
-rw-r--r--src/companion.rs84
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)),
+    )
+}