feat: add initial server + routes

This commit is contained in:
itsscb 2025-05-23 21:54:01 +02:00
parent 908d6bd67b
commit d61e6da1d2
6 changed files with 115 additions and 119 deletions

View File

@ -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"] }

View File

@ -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();
});
}

View File

@ -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,87 +17,44 @@ use tokio::sync::mpsc; // Use std::process::Stdio
type Tx = tokio::sync::mpsc::UnboundedSender<Message>;
#[tokio::main]
async fn main() {
tracing_subscriber::fmt().pretty().init();
let clients = Arc::new(Mutex::new(Vec::<Tx>::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::<Vec<_>>()
.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);
fn main() {
befehlswerk::run();
}
}
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);
// }
// }
// #[tokio::main]
// async fn main() {
// tracing_subscriber::fmt().pretty().init();
// let clients = Arc::new(Mutex::new(Vec::<Tx>::new()));
// let clients_clone = Arc::clone(&clients);
//
// for i in closed.iter().rev() {
// lock.remove(*i);
// }
// }
//}
}
//time::sleep(Duration::from_millis(500)).await;
}
});
// 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![];
//
// 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 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::<Vec<_>>()
// .join("\n")
// .into(),
// );
// {
// let mut lock = clients_clone.lock().unwrap();
// for (i, tx) in lock.iter().enumerate() {
@ -113,25 +67,21 @@ async fn main() {
// 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();
}
//
// 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<Mutex<Vec<Tx>>>) -> impl IntoResponse {
ws.on_upgrade(move |socket| handle_ws(socket, clients))

11
src/router.rs Normal file
View File

@ -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))
}

1
src/router/routes.rs Normal file
View File

@ -0,0 +1 @@
pub mod scripts;

View File

@ -0,0 +1,14 @@
use axum::response::{Html, IntoResponse};
pub async fn get_scripts() -> impl IntoResponse {
Html(
r##"
<section id="scripts">
<ul>
<li>Script1</li>
<li>Script2</li>
</ul>
<button hx-get="/scripts" hx-swap="outerHTML" hx-target="#scripts">Refresh</button>
</section>"##,
)
}