entertainarr-adapter-http 0.1.1

HTTP adapter for entertainarr
Documentation
pub mod prelude {
    pub trait ClientService: Send + Sync + 'static {
        fn get_file<P: AsRef<std::path::Path>>(&self, path: P) -> Option<&[u8]>;
    }

    #[cfg(test)]
    #[derive(Clone, Debug, Default)]
    pub struct MockClientService;

    #[cfg(test)]
    impl ClientService for MockClientService {
        fn get_file<P: AsRef<std::path::Path>>(&self, _path: P) -> Option<&[u8]> {
            None
        }
    }
}

use std::borrow::Cow;

use axum::extract::{Path, State};
use axum::http::{HeaderName, HeaderValue};

use crate::server::handler::client::prelude::ClientService;

pub async fn handle_index<S>(
    State(state): State<S>,
) -> Result<([(HeaderName, HeaderValue); 1], Vec<u8>), axum::http::StatusCode>
where
    S: crate::server::prelude::ServerState,
{
    handle(State(state), Path(Cow::Borrowed("index.html"))).await
}

pub async fn handle<S>(
    State(state): State<S>,
    Path(fname): Path<Cow<'static, str>>,
) -> Result<([(HeaderName, HeaderValue); 1], Vec<u8>), axum::http::StatusCode>
where
    S: crate::server::prelude::ServerState,
{
    let Some(content_type) = content_type(&fname) else {
        return Err(axum::http::StatusCode::NOT_FOUND);
    };
    let Some(slice) = state.client_service().get_file(fname.as_ref()) else {
        return Err(axum::http::StatusCode::NOT_FOUND);
    };
    let headers = [(CONTENT_TYPE, content_type)];
    Ok((headers, slice.to_vec()))
}

const CONTENT_TYPE: HeaderName = HeaderName::from_static("content-type");
const CONTENT_TYPE_HTML: HeaderValue = HeaderValue::from_static("text/html");
const CONTENT_TYPE_CSS: HeaderValue = HeaderValue::from_static("text/css");
const CONTENT_TYPE_JS: HeaderValue = HeaderValue::from_static("text/javascript");
const CONTENT_TYPE_WASM: HeaderValue = HeaderValue::from_static("application/wasm");

fn content_type(fname: &str) -> Option<HeaderValue> {
    if fname.ends_with("html") {
        Some(CONTENT_TYPE_HTML)
    } else if fname.ends_with("css") {
        Some(CONTENT_TYPE_CSS)
    } else if fname.ends_with("js") {
        Some(CONTENT_TYPE_JS)
    } else if fname.ends_with("wasm") {
        Some(CONTENT_TYPE_WASM)
    } else {
        None
    }
}