108 lines
3.1 KiB
Rust
108 lines
3.1 KiB
Rust
use std::{collections::HashMap, net::SocketAddr};
|
|
|
|
use futures::Future;
|
|
use include_dir::{include_dir, Dir};
|
|
use once_cell::sync::Lazy;
|
|
use warp::{
|
|
http::HeaderValue,
|
|
hyper::HeaderMap,
|
|
reply::{json, Response},
|
|
Filter, Rejection, Reply,
|
|
};
|
|
|
|
use crate::themes::{read_theme_from_dir, Theme};
|
|
|
|
static THEMES: Lazy<HashMap<String, Theme>> = Lazy::new(|| {
|
|
let mut themes = HashMap::new();
|
|
|
|
for entry in std::fs::read_dir("styles").unwrap() {
|
|
if entry.is_err() {
|
|
continue;
|
|
}
|
|
|
|
let path = entry.unwrap().path();
|
|
if path.is_dir() {
|
|
if let Some(theme) = read_theme_from_dir(path) {
|
|
themes.insert(theme.slug.clone(), theme);
|
|
}
|
|
}
|
|
}
|
|
|
|
themes
|
|
});
|
|
|
|
fn injector(theme_name: String, host: String) -> String {
|
|
if let Some(theme) = THEMES.get(&theme_name) {
|
|
// let current_addr = CURRENT_ADDRESS.get().expect("Couldn't get current address");
|
|
crate::injector::render_injector(host, theme)
|
|
} else {
|
|
"// Unknown theme, sorry!".to_string()
|
|
}
|
|
}
|
|
|
|
fn themes() -> impl Reply {
|
|
let themes: &HashMap<_, _> = &THEMES;
|
|
json(themes)
|
|
}
|
|
|
|
const PANEL_DIR: Dir = include_dir!("./src/panel");
|
|
|
|
async fn serve_panel_file(path: warp::path::Tail) -> Result<Response, Rejection> {
|
|
let mut file_name = path.as_str().to_string();
|
|
if ("/".to_string() + &file_name).ends_with("/") {
|
|
file_name.push_str("index.html");
|
|
}
|
|
|
|
if let Some(file) = PANEL_DIR.get_file(&file_name) {
|
|
let (mut head, body) = Response::new(file.contents().into()).into_parts();
|
|
|
|
let extension = file_name.rfind('.').map(|idx| &file_name[idx..]);
|
|
let content_type = match extension {
|
|
Some(".html") => "text/html; charset=utf-8",
|
|
Some(".css") => "text/css; charset=utf-8",
|
|
Some(".js") => "application/javascript; charset=utf-8",
|
|
Some(".txt") => "text/plain; charset=utf-8",
|
|
_ => "application/octet-stream",
|
|
};
|
|
|
|
head.headers
|
|
.insert("Content-Type", HeaderValue::from_str(content_type).unwrap());
|
|
|
|
return Ok(Response::from_parts(head, body));
|
|
}
|
|
|
|
Err(warp::reject::not_found())
|
|
}
|
|
|
|
pub fn serve_panel() -> (SocketAddr, impl Future<Output = ()>) {
|
|
let styles_route = {
|
|
let mut static_headers = HeaderMap::new();
|
|
for (h, v) in [
|
|
("Access-Control-Allow-Origin", "*"),
|
|
("Pragma", "no-cache"),
|
|
("Cache-Control", "no-cache"),
|
|
] {
|
|
static_headers.insert(h, HeaderValue::from_static(v));
|
|
}
|
|
|
|
warp::path("styles")
|
|
.and(warp::fs::dir("styles"))
|
|
.with(warp::reply::with::headers(static_headers))
|
|
};
|
|
|
|
let themes_list_route = warp::path("themes.json").map(themes);
|
|
let injector_route = warp::path!("theme" / String / "injector.js")
|
|
.and(warp::header("Host"))
|
|
.map(injector);
|
|
let panel_route = warp::get()
|
|
.and(warp::path::tail())
|
|
.and_then(serve_panel_file);
|
|
|
|
let routes = styles_route
|
|
.or(injector_route)
|
|
.or(themes_list_route)
|
|
.or(panel_route);
|
|
|
|
warp::serve(routes).bind_ephemeral(([127, 0, 0, 1], 0))
|
|
}
|