From d61e6da1d205eeee38124e9eb67a8e7d7fa73fe3 Mon Sep 17 00:00:00 2001 From: itsscb Date: Fri, 23 May 2025 21:54:01 +0200 Subject: [PATCH] feat: add initial server + routes --- Cargo.toml | 1 + src/lib.rs | 19 ++++ src/main.rs | 188 +++++++++++++---------------------- src/router.rs | 11 ++ src/router/routes.rs | 1 + src/router/routes/scripts.rs | 14 +++ 6 files changed, 115 insertions(+), 119 deletions(-) create mode 100644 src/router.rs create mode 100644 src/router/routes.rs create mode 100644 src/router/routes/scripts.rs diff --git a/Cargo.toml b/Cargo.toml index d54f93c..b7d91cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ serde_json = "1.0.140" sqlx = { version = "0.8.5", features = ["macros", "runtime-tokio", "sqlite", "uuid"] } tokio = { version = "1.44.2", features = ["full"] } tower = "0.5.2" +tower-http = { version = "0.6.4", features = ["fs"] } tracing = { version = "0.1.41", features = ["async-await"] } tracing-subscriber = "0.3.19" uuid = { version = "1.16.0", features = ["v4"] } diff --git a/src/lib.rs b/src/lib.rs index 48ae67f..16931c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,21 @@ +#![allow(clippy::unwrap_used)] +use router::new_router; +use tokio::net::TcpListener; +use tracing::info; + mod db; +mod router; mod script; + +pub fn run() { + let rt = tokio::runtime::Runtime::new().unwrap(); + rt.block_on(async { + tracing_subscriber::fmt::init(); + + let app = new_router(); + + let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap(); + info!("listening"=?listener.local_addr().unwrap()); + axum::serve(listener, app).await.unwrap(); + }); +} diff --git a/src/main.rs b/src/main.rs index 016ace5..26d12e3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,13 @@ -#![allow(clippy::unwrap_used, clippy::expect_used)] +#![allow(dead_code, clippy::unwrap_used, clippy::expect_used)] use axum::{ - Router, + // Router, extract::ws::{Message, WebSocket, WebSocketUpgrade}, response::IntoResponse, - routing::get, + // routing::get, }; use futures::{SinkExt, StreamExt}; -use std::{ - sync::{Arc, Mutex}, - time::Duration, -}; -use tokio::{task, time}; +use std::sync::{Arc, Mutex}; +use tokio::task; use tracing::info; use std::process::Stdio; @@ -20,118 +17,71 @@ use tokio::sync::mpsc; // Use std::process::Stdio type Tx = tokio::sync::mpsc::UnboundedSender; -#[tokio::main] -async fn main() { - tracing_subscriber::fmt().pretty().init(); - let clients = Arc::new(Mutex::new(Vec::::new())); - let clients_clone = Arc::clone(&clients); - - let (tx, mut rx) = mpsc::channel(100); - - task::spawn(async move { - let cmd = "$count = 0; while($count -lt 10000) { - #Write-Error 'test-error' - #write-warning 'test-warning' - Write-Output \"$(Get-Date -Format 'yyyy-MM-dd_HH:mm:ss'): Hello World #$($count) from PowerShell!\" - $count += 1 - }"; - spawn_and_capture(cmd, tx).await; - }); - - // In batches - but this does not preserve the order. Or does it? It's possible that stdout is - // faster than stderr. - task::spawn(async move { - loop { - let mut closed = vec![]; - - let mut messages = vec![]; - - if rx.recv_many(&mut messages, 2000).await > 0 { - let msg = Message::Text( - messages - .into_iter() - .map(|m| if m.1 { format!("[ERR]: {}", m.0) } else { m.0 }) - .collect::>() - .join("\n") - .into(), - ); - { - let mut lock = clients_clone.lock().unwrap(); - for (i, tx) in lock.iter().enumerate() { - if tx.send(msg.clone()).is_err() { - closed.push(i); - } - } - - for i in closed.iter().rev() { - lock.remove(*i); - } - } - //for message in messages { - // let msg = Message::Text(if message.1 { - // format!("[ERR]: {}", message.0).into() - // } else { - // message.0.into() - // }); - // { - // let mut lock = clients_clone.lock().unwrap(); - // for (i, tx) in lock.iter().enumerate() { - // if tx.send(msg.clone()).is_err() { - // closed.push(i); - // } - // } - // - // for i in closed.iter().rev() { - // lock.remove(*i); - // } - // } - //} - } - //time::sleep(Duration::from_millis(500)).await; - } - }); - - //task::spawn(async move { - // loop { - // let mut closed = vec![]; - // - // if let Some((line, is_err)) = rx.recv().await { - // let msg = Message::Text(if is_err { - // format!("[ERR]: {line}").into() - // } else { - // line.into() - // }); - // { - // let mut lock = clients_clone.lock().unwrap(); - // for (i, tx) in lock.iter().enumerate() { - // if tx.send(msg.clone()).is_err() { - // closed.push(i); - // } - // } - // - // for i in closed.iter().rev() { - // lock.remove(*i); - // } - // } - // - // //time::sleep(Duration::from_millis(200)).await; - // } else { - // break; - // } - // } - //}); - - let app = Router::new().route( - "/ws", - get({ - let clients = Arc::clone(&clients); - move |ws| handle_socket(ws, Arc::clone(&clients)) - }), - ); - - let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); - axum::serve(listener, app).await.unwrap(); +fn main() { + befehlswerk::run(); } +// #[tokio::main] +// async fn main() { +// tracing_subscriber::fmt().pretty().init(); +// let clients = Arc::new(Mutex::new(Vec::::new())); +// let clients_clone = Arc::clone(&clients); +// +// let (tx, mut rx) = mpsc::channel(100); +// +// task::spawn(async move { +// let cmd = "$count = 0; while($count -lt 10000) { +// #Write-Error 'test-error' +// #write-warning 'test-warning' +// Write-Output \"$(Get-Date -Format 'yyyy-MM-dd_HH:mm:ss'): Hello World #$($count) from PowerShell!\" +// $count += 1 +// }"; +// spawn_and_capture(cmd, tx).await; +// }); +// +// // In batches - but this does not preserve the order. Or does it? It's possible that stdout is +// // faster than stderr. +// task::spawn(async move { +// loop { +// let mut closed = vec![]; +// +// let mut messages = vec![]; +// +// if rx.recv_many(&mut messages, 2000).await > 0 { +// let msg = Message::Text( +// messages +// .into_iter() +// .map(|m| if m.1 { format!("[ERR]: {}", m.0) } else { m.0 }) +// .collect::>() +// .join("\n") +// .into(), +// ); +// { +// let mut lock = clients_clone.lock().unwrap(); +// for (i, tx) in lock.iter().enumerate() { +// if tx.send(msg.clone()).is_err() { +// closed.push(i); +// } +// } +// +// for i in closed.iter().rev() { +// lock.remove(*i); +// } +// } +// } +// } +// }); +// +// let app = Router::new().route( +// "/ws", +// get({ +// let clients = Arc::clone(&clients); +// move |ws| handle_socket(ws, Arc::clone(&clients)) +// }), +// ); +// +// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); +// axum::serve(listener, app).await.unwrap(); +// } async fn handle_socket(ws: WebSocketUpgrade, clients: Arc>>) -> impl IntoResponse { ws.on_upgrade(move |socket| handle_ws(socket, clients)) diff --git a/src/router.rs b/src/router.rs new file mode 100644 index 0000000..46aca27 --- /dev/null +++ b/src/router.rs @@ -0,0 +1,11 @@ +use axum::routing::{get, get_service}; +use routes::scripts::get_scripts; +use tower_http::services::ServeDir; +mod routes; + +pub fn new_router() -> axum::Router { + axum::Router::new() + .fallback_service(get_service(ServeDir::new("assets"))) + // .nest_service("/", ServeDir::new("assets")) + .route("/scripts", get(get_scripts)) +} diff --git a/src/router/routes.rs b/src/router/routes.rs new file mode 100644 index 0000000..5fc608f --- /dev/null +++ b/src/router/routes.rs @@ -0,0 +1 @@ +pub mod scripts; diff --git a/src/router/routes/scripts.rs b/src/router/routes/scripts.rs new file mode 100644 index 0000000..a170a1b --- /dev/null +++ b/src/router/routes/scripts.rs @@ -0,0 +1,14 @@ +use axum::response::{Html, IntoResponse}; + +pub async fn get_scripts() -> impl IntoResponse { + Html( + r##" +
+
    +
  • Script1
  • +
  • Script2
  • +
+ +
"##, + ) +}