chore: much better readable code
This commit is contained in:
parent
3c27eb55d7
commit
db5247c713
62
Cargo.lock
generated
62
Cargo.lock
generated
@ -52,6 +52,12 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.1"
|
||||
@ -172,6 +178,17 @@ version = "0.2.174"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.5"
|
||||
@ -196,6 +213,29 @@ version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
@ -214,6 +254,21 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
@ -249,6 +304,12 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
@ -315,6 +376,7 @@ dependencies = [
|
||||
"clap",
|
||||
"ctrlc",
|
||||
"httparse",
|
||||
"parking_lot",
|
||||
"serde",
|
||||
"shlex",
|
||||
"toml",
|
||||
|
@ -8,6 +8,7 @@ anstyle = "1"
|
||||
clap = { version = "4", features = ["derive", "string"] }
|
||||
ctrlc = "3"
|
||||
httparse = "1"
|
||||
parking_lot = { version = "0", features = ["arc_lock", "serde"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
shlex = "1"
|
||||
toml = "0"
|
||||
|
@ -1,4 +1,4 @@
|
||||
listen_at = "127.0.0.1:8080"
|
||||
|
||||
[hosts]
|
||||
"git.tuxcord.net" = "127.0.0.1:3000"
|
||||
"git.tuxcord.net" = [ "127.0.0.1:3000", "i_like_gitea", "_csrf" ]
|
||||
|
@ -19,7 +19,7 @@ pub struct Args {
|
||||
pub enum Commands {
|
||||
/// Connects to the selected IPC
|
||||
#[cfg(feature = "ipc")]
|
||||
Ipc,
|
||||
Ipc, // TODO: add -c flag for an automatic command
|
||||
}
|
||||
|
||||
fn get_clap_styles() -> clap::builder::Styles {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::{collections::HashMap, net::SocketAddr, path::PathBuf, sync::RwLock};
|
||||
use std::{collections::HashMap, net::SocketAddr, path::PathBuf};
|
||||
|
||||
use parking_lot::RwLock;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
@ -7,5 +8,5 @@ pub struct Schema {
|
||||
pub listen_at: SocketAddr,
|
||||
#[cfg(feature = "ipc")]
|
||||
pub ipc: Option<PathBuf>,
|
||||
pub hosts: RwLock<HashMap<String, SocketAddr>>,
|
||||
pub hosts: RwLock<HashMap<String, (SocketAddr, String, String)>>,
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
use core::net;
|
||||
use core::{net, str};
|
||||
use std::{
|
||||
fs,
|
||||
io::{self, BufRead, BufReader, Write, stdout},
|
||||
os::unix::net::{UnixListener, UnixStream},
|
||||
process,
|
||||
sync::{Arc, RwLockWriteGuard},
|
||||
sync::Arc,
|
||||
thread::{self, JoinHandle},
|
||||
};
|
||||
|
||||
use parking_lot::RwLockWriteGuard;
|
||||
|
||||
use crate::config;
|
||||
|
||||
pub fn start_client(config: config::Schema) {
|
||||
@ -79,41 +81,38 @@ pub fn handle_daemon_client(mut stream: UnixStream, config: Arc<config::Schema>)
|
||||
"list" => {
|
||||
_ = writeln!(stream, "aquiring read lock");
|
||||
let rlock = config.hosts.read();
|
||||
match rlock {
|
||||
Ok(lock) => {
|
||||
_ = writeln!(stream, "{lock:#?}");
|
||||
}
|
||||
Err(err) => {
|
||||
_ = writeln!(stream, "err with read lock: {err:?}");
|
||||
}
|
||||
};
|
||||
_ = writeln!(stream, "{rlock:#?}");
|
||||
}
|
||||
"create" => {
|
||||
if let [name, value] = args {
|
||||
match value.parse::<net::SocketAddr>() {
|
||||
Ok(addr) => {
|
||||
_ = writeln!(stream, "aquiring write lock");
|
||||
let wlock = config.hosts.write();
|
||||
match wlock {
|
||||
Ok(mut lock) => {
|
||||
lock.insert(name.to_string(), addr);
|
||||
let lock = RwLockWriteGuard::downgrade(lock);
|
||||
_ = writeln!(stream, "{lock:#?}");
|
||||
}
|
||||
Err(err) => {
|
||||
_ = writeln!(
|
||||
stream,
|
||||
"err with write lock: {err:?}"
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
Err(err) => {
|
||||
_ = writeln!(
|
||||
stream,
|
||||
"err: parsing value as socket addres {err:?}"
|
||||
);
|
||||
}
|
||||
if let Ok([value, id, csrf]) =
|
||||
<_ as TryInto<[&str; 3]>>::try_into(
|
||||
value.split(',').take(3).collect::<Vec<_>>(),
|
||||
)
|
||||
{
|
||||
match value.parse::<net::SocketAddr>() {
|
||||
Ok(addr) => {
|
||||
_ = writeln!(stream, "aquiring write lock");
|
||||
let mut wlock = config.hosts.write();
|
||||
wlock.insert(
|
||||
name.to_string(),
|
||||
(addr, id.to_string(), csrf.to_string()),
|
||||
);
|
||||
let rlock = RwLockWriteGuard::downgrade(wlock);
|
||||
_ = writeln!(stream, "{rlock:#?}");
|
||||
}
|
||||
Err(err) => {
|
||||
_ = writeln!(
|
||||
stream,
|
||||
"err: parsing value as socket addres {err:?}"
|
||||
);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
_ = writeln!(
|
||||
stream,
|
||||
"err: value wasn't 3 comma separated values"
|
||||
);
|
||||
};
|
||||
} else {
|
||||
_ = writeln!(
|
||||
@ -125,17 +124,10 @@ pub fn handle_daemon_client(mut stream: UnixStream, config: Arc<config::Schema>)
|
||||
"delete" => {
|
||||
if let [name] = args {
|
||||
_ = writeln!(stream, "aquiring write lock");
|
||||
let wlock = config.hosts.write();
|
||||
match wlock {
|
||||
Ok(mut lock) => {
|
||||
lock.remove(name);
|
||||
let lock = RwLockWriteGuard::downgrade(lock);
|
||||
_ = writeln!(stream, "{lock:#?}");
|
||||
}
|
||||
Err(err) => {
|
||||
_ = writeln!(stream, "err with write lock: {err:?}");
|
||||
}
|
||||
};
|
||||
let mut wlock = config.hosts.write();
|
||||
wlock.remove(name);
|
||||
let lock = RwLockWriteGuard::downgrade(wlock);
|
||||
_ = writeln!(stream, "{lock:#?}");
|
||||
} else {
|
||||
_ = writeln!(stream, "invalid arg count, expected a name");
|
||||
}
|
||||
|
58
src/main.rs
58
src/main.rs
@ -1,5 +1,10 @@
|
||||
//! # Tuxcord Reverse Proxy Header Authenthication
|
||||
#![feature(rwlock_downgrade, try_blocks)]
|
||||
#![feature(
|
||||
rwlock_downgrade,
|
||||
try_blocks,
|
||||
iterator_try_collect,
|
||||
anonymous_lifetime_in_impl_trait
|
||||
)]
|
||||
|
||||
use std::{
|
||||
fs::File,
|
||||
@ -11,10 +16,13 @@ use std::{
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
use crate::utils::headers::HeadersExt;
|
||||
|
||||
pub mod args;
|
||||
pub mod config;
|
||||
#[cfg(feature = "ipc")]
|
||||
pub mod ipc;
|
||||
pub mod utils;
|
||||
|
||||
use args::Args;
|
||||
|
||||
@ -78,54 +86,30 @@ fn handle_client(client: &mut TcpStream, config: &config::Schema) -> Result<(),
|
||||
let mut header_buf = [0u8; 1024 * 8];
|
||||
let mut read_pos = 0usize;
|
||||
|
||||
let pos = loop {
|
||||
let mut headers;
|
||||
let (pos, req) = loop {
|
||||
headers = [httparse::EMPTY_HEADER; 16];
|
||||
let mut req = httparse::Request::new(&mut headers);
|
||||
|
||||
let Ok(n) = client.read(&mut header_buf[read_pos..]) else {
|
||||
return Err("error reading stream");
|
||||
};
|
||||
read_pos += n;
|
||||
|
||||
let pos = header_buf
|
||||
.windows(b"\r\n\r\n".len())
|
||||
.position(|w| w == b"\r\n\r\n");
|
||||
if let Some(pos) = pos {
|
||||
break pos;
|
||||
};
|
||||
if let Ok(httparse::Status::Complete(n)) = req.parse(&header_buf[0..read_pos]) {
|
||||
break (n - b"\r\n\r\n".len(), req);
|
||||
}
|
||||
};
|
||||
|
||||
let mut headers = [httparse::EMPTY_HEADER; 16];
|
||||
let mut req = httparse::Request::new(&mut headers);
|
||||
let Ok(httparse::Status::Complete(_)) =
|
||||
httparse::Request::parse(&mut req, &header_buf[0..(pos + b"\r\n\r\n".len())])
|
||||
else {
|
||||
return Err("parsing request was not complete");
|
||||
};
|
||||
let theres_body = req.headers.has_any(["conten-length", "transfer-encoding"]);
|
||||
|
||||
let theres_body = req
|
||||
.headers
|
||||
.iter()
|
||||
.any(|header| header.name.to_lowercase() == "content-length")
|
||||
|| req
|
||||
.headers
|
||||
.iter()
|
||||
.any(|header| header.name.to_lowercase() == "transfer-encoding");
|
||||
|
||||
let Some(header) = req
|
||||
.headers
|
||||
.iter()
|
||||
.find(|header| header.name.to_lowercase() == "host")
|
||||
else {
|
||||
let Some(host_header) = req.headers.get("host") else {
|
||||
return Err("failed to find \"host\" header");
|
||||
};
|
||||
|
||||
let Ok(host_header) = String::from_utf8(header.value.to_vec()) else {
|
||||
return Err("\"host\" header is not valid UTF-8");
|
||||
};
|
||||
|
||||
// Now find that header and pas everything
|
||||
let Ok(read_hosts) = config.hosts.read() else {
|
||||
return Err("poisoned RwLock");
|
||||
};
|
||||
let Some(addr) = read_hosts.get(&host_header) else {
|
||||
let read_hosts = config.hosts.read();
|
||||
let Some((addr, _, _)) = read_hosts.get(host_header.as_ref()) else {
|
||||
return Err("host not in hashmap");
|
||||
};
|
||||
|
||||
|
26
src/utils.rs
Normal file
26
src/utils.rs
Normal file
@ -0,0 +1,26 @@
|
||||
pub mod headers {
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub trait HeadersExt<'a> {
|
||||
fn has_any(&self, headers: impl IntoIterator<Item = &'_ str>) -> bool {
|
||||
headers.into_iter().any(|h| self.has(h))
|
||||
}
|
||||
fn has_all(&self, headers: impl IntoIterator<Item = &'_ str>) -> bool {
|
||||
headers.into_iter().all(|h| self.has(h))
|
||||
}
|
||||
fn has(&self, header: &str) -> bool;
|
||||
fn get(&self, header: &str) -> Option<Cow<'a, str>>;
|
||||
}
|
||||
|
||||
impl<'a> HeadersExt<'a> for &mut [httparse::Header<'a>] {
|
||||
fn has(&self, header: &str) -> bool {
|
||||
self.iter().any(|h| h.name.eq_ignore_ascii_case(header))
|
||||
}
|
||||
|
||||
fn get(&self, header: &str) -> Option<Cow<'a, str>> {
|
||||
self.iter()
|
||||
.find(|h| h.name.eq_ignore_ascii_case(header))
|
||||
.map(|h| String::from_utf8_lossy(h.value))
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user