80 lines
2.5 KiB
Rust
80 lines
2.5 KiB
Rust
use axum::{Router, response::Html, routing::get};
|
|
use std::{fs::OpenOptions, io::{BufRead, Read}, path::Path};
|
|
use tower_http::services::ServeDir;
|
|
|
|
const PUBKEY_PATH: &str = "./pubkeys/public_keys.json";
|
|
lazy_static::lazy_static! {
|
|
static ref PUBLIC_KEYS: Vec<Vec<u8>> = load_public_keys(PUBKEY_PATH).expect("static path");
|
|
}
|
|
|
|
type Error = Box<dyn std::error::Error>;
|
|
type Result<T> = std::result::Result<T, Error>;
|
|
|
|
fn load_public_keys(path: impl AsRef<Path>) -> std::io::Result<Vec<Vec<u8>>> {
|
|
// Open the file
|
|
let f = OpenOptions::new()
|
|
.read(true)
|
|
.write(false)
|
|
.open(path)?;
|
|
|
|
// Wrap it in a BufReader for efficient line-by-line reading
|
|
let reader = std::io::BufReader::new(f);
|
|
|
|
let mut public_keys = Vec::new();
|
|
|
|
// Iterate over each line in the file
|
|
for line_result in reader.lines() {
|
|
let line = line_result?; // Handle potential IO errors during reading
|
|
|
|
// Skip empty lines or lines with only whitespace
|
|
let trimmed_line = line.trim();
|
|
if trimmed_line.is_empty() {
|
|
continue;
|
|
}
|
|
|
|
// Deserialize the line (which is a single JSON array) into a Vec<u8>
|
|
let key: Vec<u8> = serde_json::from_str(trimmed_line).map_err(|e| {
|
|
std::io::Error::new(
|
|
std::io::ErrorKind::InvalidData,
|
|
format!("Failed to parse JSON line: {}", e),
|
|
)
|
|
})?;
|
|
|
|
public_keys.push(key);
|
|
}
|
|
|
|
Ok(public_keys)
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<()> {
|
|
// build our application with a single route
|
|
let app = Router::new()
|
|
.route("/", get(serve_path("./routes/root/index.html")?))
|
|
.route("/who", get(serve_path("./routes/who/index.html")?))
|
|
.route("/api/pubkey", get(async || select_key(&PUBLIC_KEYS)))
|
|
.route("/contact", get(serve_path("./routes/contact/index.html")?))
|
|
.nest_service("/routes", ServeDir::new("./routes"));
|
|
|
|
// run our app with hyper, listening globally on port 3000
|
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
|
axum::serve(listener, app).await.unwrap();
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn select_key(pks: &Vec<Vec<u8>>) -> String {
|
|
let idx = getrandom::u64().expect("random integer") as usize % pks.len();
|
|
serde_json::to_string(&pks[idx]).expect("serialize vec of bytes")
|
|
}
|
|
|
|
fn serve_path(path: impl AsRef<std::path::Path>) -> Result<Html<String>> {
|
|
let mut s = String::new();
|
|
OpenOptions::new()
|
|
.read(true)
|
|
.write(false)
|
|
.open(path)?
|
|
.read_to_string(&mut s)?;
|
|
|
|
Ok(Html(s))
|
|
}
|