Added port target spawning support, improved config & session data
This commit is contained in:
parent
cf94b742e4
commit
b694c11d78
67
Cargo.lock
generated
67
Cargo.lock
generated
|
@ -38,6 +38,15 @@ version = "1.0.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.28"
|
||||
|
@ -222,6 +231,16 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
|
@ -311,6 +330,7 @@ dependencies = [
|
|||
"serde_yaml",
|
||||
"tokio",
|
||||
"tower",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -342,6 +362,12 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.0.12"
|
||||
|
@ -538,6 +564,21 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||
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.27.0"
|
||||
|
@ -642,18 +683,44 @@ version = "0.2.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.0"
|
||||
|
|
|
@ -13,6 +13,7 @@ tower = { version = "0.4", features = ["full"] }
|
|||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_yaml = "0.9"
|
||||
lazy_static = "1.4.0"
|
||||
url = "2.3.0"
|
||||
|
||||
[[bin]]
|
||||
name = "odproxy"
|
||||
|
|
9
conf.rs
9
conf.rs
|
@ -21,7 +21,8 @@ pub struct RootConf {
|
|||
pub struct ProxyConf {
|
||||
pub hosts: Vec<String>,
|
||||
pub target: String,
|
||||
pub socket: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub socket: bool,
|
||||
pub spawn: Option<SpawnConf>,
|
||||
pub timeout: Option<u64>
|
||||
}
|
||||
|
@ -29,8 +30,10 @@ pub struct ProxyConf {
|
|||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct SpawnConf {
|
||||
pub command: String,
|
||||
pub args: Option<Vec<String>>,
|
||||
pub envs: Option<Vec<(String, String)>>
|
||||
#[serde(default)]
|
||||
pub args: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub envs: Vec<(String, String)>
|
||||
}
|
||||
|
||||
fn load() -> RootConf {
|
||||
|
|
6
main.rs
6
main.rs
|
@ -26,9 +26,7 @@ async fn run(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
|
|||
let mut request_builder = Request::builder().method(req.method());
|
||||
let path = req.uri().path_and_query().unwrap().as_str();
|
||||
|
||||
let is_socket = p.socket.unwrap_or(false);
|
||||
|
||||
if is_socket {
|
||||
if p.socket {
|
||||
request_builder = request_builder.uri(hyperlocal::Uri::new(&p.target, path));
|
||||
} else {
|
||||
let url = p.target.clone() + path;
|
||||
|
@ -44,7 +42,7 @@ async fn run(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
|
|||
let body = req.into_body();
|
||||
let nreq = request_builder.body(body).unwrap();
|
||||
|
||||
if is_socket {
|
||||
if p.socket {
|
||||
Client::unix().request(nreq).await
|
||||
} else {
|
||||
Client::new().request(nreq).await
|
||||
|
|
86
services.rs
86
services.rs
|
@ -1,8 +1,21 @@
|
|||
use std::{process::Stdio, time::{Duration, SystemTime, UNIX_EPOCH}, path::Path, io::Error, thread};
|
||||
use std::{process::Stdio, time::{Duration, SystemTime, UNIX_EPOCH}, path::Path, io::Error, thread, net::SocketAddr};
|
||||
use tokio::{process::{Command, Child}, time::sleep, fs};
|
||||
use url::Url;
|
||||
use std::net::TcpStream;
|
||||
use std::net::{ToSocketAddrs};
|
||||
|
||||
use crate::{data::{SERVICES, ServiceData}, conf::{ProxyConf, self}};
|
||||
|
||||
fn target_to_address(target: &str) -> Option<SocketAddr> {
|
||||
Url::parse(target)
|
||||
.ok()
|
||||
.and_then(|url| {
|
||||
let host = url.host()?;
|
||||
let port = url.port()?;
|
||||
(host.to_string(), port).to_socket_addrs().ok().and_then(|addr| addr.last())
|
||||
})
|
||||
}
|
||||
|
||||
fn modify_service_data<F>(name: &String, modify_fn: F)
|
||||
where F: FnOnce(&mut ServiceData)
|
||||
{
|
||||
|
@ -12,41 +25,31 @@ fn modify_service_data<F>(name: &String, modify_fn: F)
|
|||
}
|
||||
}
|
||||
|
||||
fn set_service_running(name: &String) {
|
||||
modify_service_data(name, |s| {
|
||||
s.running = true;
|
||||
});
|
||||
}
|
||||
|
||||
fn set_service_last_active(name: &String) {
|
||||
modify_service_data(name, |s| {
|
||||
s.last_active = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
|
||||
});
|
||||
}
|
||||
|
||||
fn is_service_running(name: &String) -> bool {
|
||||
if let Some(service_data) = SERVICES.lock().unwrap().get(name) {
|
||||
service_data.running
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn check_service(name: &String, proxy: &ProxyConf) {
|
||||
|
||||
if proxy.spawn.is_some() {
|
||||
if proxy.socket.unwrap_or(false) && SERVICES.lock().unwrap().get(name).unwrap().child.is_none() {
|
||||
|
||||
let mut ready = false;
|
||||
let mut running = false;
|
||||
modify_service_data(name, |s| {
|
||||
ready = s.child.is_some();
|
||||
running = s.running;
|
||||
s.last_active = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
|
||||
});
|
||||
|
||||
if !ready && proxy.socket {
|
||||
let path = Path::new(&proxy.target);
|
||||
if path.exists() {
|
||||
fs::remove_file(path).await.unwrap();
|
||||
}
|
||||
}
|
||||
start_service(name, &proxy);
|
||||
if !is_service_running(name) {
|
||||
wait_for_service(&proxy).await;
|
||||
set_service_running(name);
|
||||
|
||||
if !running {
|
||||
start_service(name, proxy);
|
||||
wait_for_service(proxy).await;
|
||||
modify_service_data(name, |s| s.running = true);
|
||||
}
|
||||
set_service_last_active(name);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -59,8 +62,8 @@ fn start_service(name: &String, proxy: &ProxyConf) -> bool {
|
|||
return;
|
||||
}
|
||||
let command = spawn.command.clone();
|
||||
let args = spawn.args.clone().unwrap_or(vec![]);
|
||||
let envs = spawn.envs.clone().unwrap_or(vec![]);
|
||||
let args = spawn.args.clone();
|
||||
let envs = spawn.envs.clone();
|
||||
let spawned_child = create_child(command, args, envs);
|
||||
match spawned_child {
|
||||
Ok(child) => {
|
||||
|
@ -74,7 +77,6 @@ fn start_service(name: &String, proxy: &ProxyConf) -> bool {
|
|||
}
|
||||
|
||||
fn stop_service(name: &String) {
|
||||
println!("Stopped");
|
||||
modify_service_data(name, |s| {
|
||||
match s.child.as_mut() {
|
||||
Some(c) => {
|
||||
|
@ -88,9 +90,25 @@ fn stop_service(name: &String) {
|
|||
}
|
||||
|
||||
async fn wait_for_service(proxy: &ProxyConf) {
|
||||
let path = Path::new(&proxy.target);
|
||||
while !path.exists() {
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
if proxy.socket {
|
||||
|
||||
let path = Path::new(&proxy.target);
|
||||
while !path.exists() {
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if let Some(address) = target_to_address(&proxy.target) {
|
||||
loop {
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
match TcpStream::connect(address) {
|
||||
Ok(_) => break,
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +117,7 @@ pub async fn prepare_services() {
|
|||
for proxy in conf::get().proxy.into_iter() {
|
||||
hashmap.insert(proxy.0, ServiceData::new());
|
||||
}
|
||||
|
||||
|
||||
let interval_duration = Duration::from_secs(10);
|
||||
thread::spawn(move || {
|
||||
loop {
|
||||
|
|
Loading…
Reference in a new issue