Refactor and enhance Archipelago setup and API

- Revamped GETTING_STARTED.md for clarity and completeness, detailing the Docker development environment and installation steps.
- Updated Cargo.lock and Cargo.toml to replace deprecated dependencies and add new ones, including hyper-ws-listener and env_logger.
- Improved WebSocket handling in the API to support upgrades and error management.
- Enhanced Neode UI scripts to manage Docker containers during development.
- Adjusted dummy app configurations for accurate LAN addresses.
- Sorted app entries in the UI for better organization and accessibility.
This commit is contained in:
Dorian
2026-01-27 22:47:51 +00:00
parent 4126aa0b33
commit 10fa19df66
17 changed files with 1370 additions and 450 deletions
+97 -70
View File
@@ -40,15 +40,15 @@ dependencies = [
"http-body 1.0.1",
"http-body-util",
"hyper 0.14.32",
"hyper-tungstenite",
"hyper-util",
"hyper-ws-listener",
"serde",
"serde_json",
"serde_yaml",
"thiserror",
"tokio",
"tokio-test",
"tokio-tungstenite 0.20.1",
"tokio-tungstenite",
"toml",
"tower",
"tower-http",
@@ -325,6 +325,19 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "env_logger"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
dependencies = [
"humantime",
"is-terminal",
"log",
"regex",
"termcolor",
]
[[package]]
name = "equivalent"
version = "1.0.2"
@@ -549,6 +562,12 @@ version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
[[package]]
name = "hermit-abi"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
name = "http"
version = "0.2.12"
@@ -616,6 +635,12 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humantime"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424"
[[package]]
name = "hyper"
version = "0.14.32"
@@ -676,19 +701,6 @@ dependencies = [
"tokio-native-tls",
]
[[package]]
name = "hyper-tungstenite"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "226df6fd0aece319a325419d770aa9d947defa60463f142cd82b329121f906a3"
dependencies = [
"hyper 0.14.32",
"pin-project",
"tokio",
"tokio-tungstenite 0.19.0",
"tungstenite 0.19.0",
]
[[package]]
name = "hyper-util"
version = "0.1.19"
@@ -716,6 +728,23 @@ dependencies = [
"windows-registry",
]
[[package]]
name = "hyper-ws-listener"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcbfe4981e45b0a7403a55d4af12f8d30e173e722409658c3857243990e72180"
dependencies = [
"anyhow",
"base64 0.21.7",
"env_logger",
"futures",
"hyper 0.14.32",
"log",
"sha-1",
"tokio",
"tokio-tungstenite",
]
[[package]]
name = "iana-time-zone"
version = "0.1.64"
@@ -869,6 +898,17 @@ version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
[[package]]
name = "is-terminal"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
dependencies = [
"hermit-abi",
"libc",
"windows-sys 0.61.2",
]
[[package]]
name = "itoa"
version = "1.0.17"
@@ -1070,26 +1110,6 @@ version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "pin-project"
version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pin-project-lite"
version = "0.2.16"
@@ -1189,6 +1209,18 @@ dependencies = [
"bitflags 2.10.0",
]
[[package]]
name = "regex"
version = "1.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.13"
@@ -1395,6 +1427,17 @@ dependencies = [
"unsafe-libyaml",
]
[[package]]
name = "sha-1"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha1"
version = "0.10.6"
@@ -1558,6 +1601,15 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.69"
@@ -1657,18 +1709,6 @@ dependencies = [
"tokio-stream",
]
[[package]]
name = "tokio-tungstenite"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec509ac96e9a0c43427c74f003127d953a265737636129424288d27cb5c4b12c"
dependencies = [
"futures-util",
"log",
"tokio",
"tungstenite 0.19.0",
]
[[package]]
name = "tokio-tungstenite"
version = "0.20.1"
@@ -1677,10 +1717,8 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c"
dependencies = [
"futures-util",
"log",
"native-tls",
"tokio",
"tokio-native-tls",
"tungstenite 0.20.1",
"tungstenite",
]
[[package]]
@@ -1842,25 +1880,6 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "tungstenite"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67"
dependencies = [
"byteorder",
"bytes",
"data-encoding",
"http 0.2.12",
"httparse",
"log",
"rand",
"sha1",
"thiserror",
"url",
"utf-8",
]
[[package]]
name = "tungstenite"
version = "0.20.1"
@@ -1873,7 +1892,6 @@ dependencies = [
"http 0.2.12",
"httparse",
"log",
"native-tls",
"rand",
"sha1",
"thiserror",
@@ -2045,6 +2063,15 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "winapi-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "windows-core"
version = "0.62.2"
+2 -2
View File
@@ -26,8 +26,8 @@ http-body-util = "0.1"
http-body = "1.0"
tower = "0.5"
tower-http = { version = "0.6", features = ["cors", "trace"] }
tokio-tungstenite = { version = "0.20", features = ["native-tls"] }
hyper-tungstenite = { version = "0.10", default-features = false }
hyper-ws-listener = "0.3.0"
tokio-tungstenite = "0.20"
futures-util = "0.3"
# Our modules
+35 -30
View File
@@ -3,9 +3,10 @@ use crate::config::Config;
use anyhow::Result;
use futures_util::{SinkExt, StreamExt};
use hyper::{Method, Request, Response, StatusCode};
use hyper_tungstenite::tungstenite::Message;
use hyper_ws_listener::WsStream;
use std::sync::Arc;
use tracing::{debug, error, info};
use tokio_tungstenite::tungstenite::Message;
use tracing::{debug, info};
pub struct ApiHandler {
_config: Config,
@@ -58,40 +59,44 @@ impl ApiHandler {
async fn handle_websocket(
req: Request<hyper::Body>,
) -> Result<Response<hyper::Body>> {
if !hyper_tungstenite::is_upgrade_request(&req) {
return Ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(hyper::Body::from("Expected WebSocket upgrade"))?);
}
let (response, ws_fut) = hyper_tungstenite::upgrade(req, None)
let (response, ws_fut_opt) = hyper_ws_listener::create_ws(req)
.map_err(|e| anyhow::anyhow!("WebSocket upgrade failed: {}", e))?;
// Spawn a task to hold the connection open and avoid EPIPE when the UI connects
tokio::spawn(async move {
let mut ws_stream = match ws_fut.await {
Ok(s) => s,
Err(e) => {
error!("WebSocket handshake failed: {}", e);
return;
}
};
info!("WebSocket /ws/db connected");
// Keep connection open; UI may send/receive JSON patches. For now just accept and ignore.
while let Some(msg) = ws_stream.next().await {
match msg {
Ok(Message::Close(_)) => break,
Ok(Message::Ping(data)) => {
let _ = ws_stream.send(Message::Pong(data)).await;
// Spawn a task to hold the connection open if upgrade future exists
if let Some(ws_fut) = ws_fut_opt {
tokio::spawn(async move {
let ws_stream: WsStream = match ws_fut.await {
Ok(Ok(s)) => s,
Ok(Err(e)) => {
debug!("WebSocket handshake failed (hyper): {}", e);
return;
}
Ok(_) => {}
Err(e) => {
debug!("WebSocket stream error: {}", e);
break;
debug!("WebSocket task join failed: {}", e);
return;
}
};
info!("WebSocket /ws/db connected");
let (mut tx, mut rx) = ws_stream.split();
// Keep connection open; UI may send/receive JSON patches. For now just accept and ignore.
while let Some(msg) = rx.next().await {
match msg {
Ok(Message::Close(_)) => break,
Ok(Message::Ping(data)) => {
let _ = tx.send(Message::Pong(data)).await;
}
Ok(_) => {}
Err(e) => {
debug!("WebSocket stream error: {}", e);
break;
}
}
}
}
});
info!("WebSocket /ws/db disconnected");
});
}
Ok(response)
}
+1
View File
@@ -48,6 +48,7 @@ impl Server {
if let Err(e) = Http::new()
.serve_connection(stream, service)
.with_upgrades()
.await
{
error!("Error serving connection from {}: {}", peer_addr, e);