feat: get stuff from X.cc.blek.codes from $DOCROOT/X

This commit is contained in:
b1ek 2024-08-22 12:32:09 +10:00
parent bc288c7b5b
commit 53d7398ce2
Signed by: blek
GPG Key ID: 14546221E3595D0C
7 changed files with 416 additions and 14 deletions

261
Cargo.lock generated
View File

@ -17,6 +17,21 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "atomic-waker"
version = "1.1.2"
@ -50,6 +65,12 @@ version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "bytes"
version = "1.7.1"
@ -69,9 +90,13 @@ dependencies = [
name = "ccDaemon"
version = "0.1.0"
dependencies = [
"chrono",
"http-body-util",
"hyper",
"hyper-util",
"mime",
"mime-sniffer",
"mime_guess",
"tokio",
]
@ -81,6 +106,26 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "equivalent"
version = "1.0.1"
@ -256,6 +301,40 @@ dependencies = [
"tracing",
]
[[package]]
name = "iana-time-zone"
version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "idna"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "2.4.0"
@ -272,6 +351,15 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "js-sys"
version = "0.3.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.158"
@ -288,12 +376,50 @@ dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "matches"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime-sniffer"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e98f7cfbbaf64674624e2aa35327d75e3de8e4d1b2555ef70dcf0c107a95490"
dependencies = [
"mime",
"url",
]
[[package]]
name = "mime_guess"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "miniz_oxide"
version = "0.7.4"
@ -315,6 +441,15 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "object"
version = "0.36.3"
@ -353,6 +488,12 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "percent-encoding"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
[[package]]
name = "pin-project"
version = "1.1.5"
@ -475,6 +616,21 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "tinyvec"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.39.3"
@ -569,12 +725,53 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "unicase"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"version_check",
]
[[package]]
name = "unicode-bidi"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
dependencies = [
"tinyvec",
]
[[package]]
name = "url"
version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
dependencies = [
"idna",
"matches",
"percent-encoding",
]
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "want"
version = "0.3.1"
@ -590,6 +787,70 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
dependencies = [
"cfg-if",
"once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.52.0"

View File

@ -4,7 +4,11 @@ version = "0.1.0"
edition = "2021"
[dependencies]
chrono = "0.4.38"
http-body-util = "0.1.2"
hyper = { version = "1.4.1", features = ["full"] }
hyper-util = { version = "0.1.7", features = ["full"] }
mime = "0.3.17"
mime-sniffer = "0.1.2"
mime_guess = "2.0.5"
tokio = { version = "1.39.3", features = ["full"] }

View File

@ -1,13 +1,24 @@
use std::{env::var, net::SocketAddr};
use std::{env::var, net::SocketAddr, path::{Path, PathBuf}};
#[derive(Debug, Clone)]
pub struct Env {
pub listen: SocketAddr
pub listen: SocketAddr,
pub docroot: PathBuf,
pub tld: String
}
impl Env {
pub fn get_doc_for_sni<T: AsRef<Path>>(&self, sni: T) -> PathBuf {
self.docroot.clone().join(sni)
}
}
impl Default for Env {
fn default() -> Self {
Self {
listen: var("LISTEN").unwrap().parse().unwrap(),
listen: var("LISTEN").expect("LISTEN").parse().unwrap(),
docroot: var("DOCROOT").expect("DOCROOT").parse().unwrap(),
tld: var("CC_TLD").unwrap_or("cc.blek.codes".into())
}
}
}

52
src/filegetter.rs Normal file
View File

@ -0,0 +1,52 @@
use std::{collections::HashMap, fs, path::PathBuf, time::Duration};
use chrono::{DateTime, Local};
use mime::Mime;
use mime_sniffer::MimeTypeSnifferExt;
#[derive(Debug, Clone)]
struct CachedFile {
pub die: DateTime<Local>,
pub data: Vec<u8>,
pub mime: Mime,
}
#[derive(Debug, Clone)]
pub struct FileGetter {
cached_files: HashMap<PathBuf, CachedFile>
}
impl FileGetter {
pub fn new() -> Self {
Self {
cached_files: HashMap::new()
}
}
pub fn get_file<T: Into<PathBuf>>(&mut self, file: T) -> Result<Option<(Vec<u8>, Mime)>, Box<dyn std::error::Error>> {
let file_path: PathBuf = file.into();
if let Some(file) = self.cached_files.get_mut(&file_path) {
file.die = Local::now() + Duration::from_secs(15);
Ok(Some((file.data.clone(), file.mime.clone())))
} else {
let mut file_path = file_path;
if file_path.is_dir() { file_path = file_path.join("index.html"); }
if ! file_path.is_file() { return Ok(None) }
let buf = fs::read(&file_path)?;
let mime = buf.sniff_mime_type_ext().unwrap_or(mime_guess::from_path(&file_path).first_or(mime::APPLICATION_OCTET_STREAM));
if self.cached_files.len() < 100 {
self.cached_files.insert(file_path, CachedFile {
die: Local::now() + Duration::from_secs(15),
data: buf.clone(),
mime: mime.clone()
});
}
Ok(Some((buf, mime)))
}
}
}

View File

@ -1,7 +1,11 @@
use std::sync::Arc;
use hyper::server::conn::http1;
use hyper_util::rt::TokioIo;
use tokio::net::TcpListener;
use std::sync::Mutex;
mod filegetter;
mod sni;
mod env;
@ -12,14 +16,23 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("Running on {}", env.listen);
let listener = TcpListener::bind(env.listen).await?;
let files = Arc::new(Mutex::new(filegetter::FileGetter::new()));
loop {
let (stream, _) = listener.accept().await?;
let client_ip = stream.peer_addr().map(|x| Some(x)).unwrap_or(None);
let io = TokioIo::new(stream);
let svc = sni::SniWebsitesService {};
let env = env.clone();
let files = files.clone();
tokio::task::spawn(async move {
let svc = sni::SniWebsitesService {
client_ip,
env: env.clone(),
files
};
if let Err(e) = http1::Builder::new()
.serve_connection(io, svc)
.await {

View File

@ -1,14 +1,22 @@
use std::future::Future;
use std::net::SocketAddr;
use std::pin::Pin;
use std::sync::Arc;
use http_body_util::Full;
use hyper::Response;
use hyper::{Response, http::response::Builder};
use hyper::{service::Service, Request};
use hyper::body::{Bytes, Incoming as IncomingBody};
use std::sync::Mutex;
#[derive(Debug, Clone, Copy)]
use crate::env::Env;
use crate::filegetter::FileGetter;
#[derive(Debug)]
pub struct SniWebsitesService {
pub client_ip: Option<SocketAddr>,
pub env: Env,
pub files: Arc<Mutex<FileGetter>>
}
impl SniWebsitesService {
@ -17,18 +25,70 @@ impl SniWebsitesService {
}
}
fn res_builder() -> Builder {
Response::builder()
.header("Server", "blek! CC 1.0")
}
fn check_uri(uri: String) -> bool {
if ! uri.starts_with('/') { return false }
for seg in uri.split("/") {
if seg.starts_with(".") {
return false
}
}
true
}
fn serve_file(sni: String, req: Request<IncomingBody>, env: &Env, files: Arc<Mutex<FileGetter>>) -> Response<Full<Bytes>> {
let docpath = env.get_doc_for_sni(sni);
let uri = req.uri().path().to_string();
if ! check_uri(uri.to_string()) {
return res_builder()
.status(400)
.body(SniWebsitesService::make_body("illegal URI"))
.unwrap()
}
let path = docpath.join(uri.trim_start_matches('/'));
let file = files.lock().unwrap().get_file(path).unwrap();
if let Some(file) = file {
res_builder()
.header("Content-Type", file.1.to_string())
.body(SniWebsitesService::make_body(file.0))
.unwrap()
} else {
res_builder()
.header("Content-Type", "text/html")
.body(SniWebsitesService::make_body("<h1>not found!</h1><p>this file is not found</p>"))
.unwrap()
}
}
impl Service<Request<IncomingBody>> for SniWebsitesService {
type Response = Response<Full<Bytes>>;
type Error = hyper::Error;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn call(&self, _req: Request<IncomingBody>) -> Self::Future {
let res = Response::builder()
.header("Server", "blek! CC 1.0")
.body(Self::make_body("miau"))
.unwrap();
fn call(&self, req: Request<IncomingBody>) -> Self::Future {
let res =
if let Some(sni) = req.headers().get("x-forwarded-host") {
let sni = sni.to_str().unwrap();
let sni = sni.replace(&(".".to_string() + &self.env.tld), "");
serve_file(sni, req, &self.env, self.files.clone())
} else {
res_builder()
.status(400)
.header("Content-Type", "text/plain")
.body(Self::make_body("refusing to answer to a non proxied request"))
.unwrap()
};
Box::pin(async { Ok(res) })
}
}

1
www/blek/index.html Normal file
View File

@ -0,0 +1 @@
heyo x3