Skip to content

Commit

Permalink
Add a DIY function for capwords filter
Browse files Browse the repository at this point in the history
Implement server session timeout
  • Loading branch information
dormant-user committed Sep 23, 2024
1 parent cd72b7e commit f5ed531
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ path = "src/main.rs"
rustdoc-args = ["--document-private-items"]

[dependencies]
actix = "0.13.5"
actix-rt = "2.10.0"
actix-web = { version = "4.9.0", features = ["openssl"] }
actix-ws = "0.3.0"
Expand All @@ -46,7 +47,6 @@ reqwest = { version = "0.11", features = ["blocking", "json"] }
minijinja = { version = "2.3.1", features = ["loader"] }
url = "2.5.2"
regex = "1.10.6"
Inflector = "0.11"
openssl = "0.10.64"
dotenv = "0.15.0"
futures-util = "0.3.30"
Expand Down
2 changes: 0 additions & 2 deletions src/resources/disks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ use regex::Regex;
use serde_json::Value;
use crate::squire;

// todo: tested only on macOS

/// Function to convert byte size to human-readable format.
///
/// # Arguments
Expand Down
3 changes: 1 addition & 2 deletions src/resources/info.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::collections::HashMap;
use chrono::Utc;
use inflector::cases::titlecase::to_title_case;
use sysinfo::{DiskExt, System, SystemExt};
use crate::{squire, resources};

Expand Down Expand Up @@ -44,7 +43,7 @@ pub fn get_sys_info() -> HashMap<&'static str, HashMap<&'static str, String>> {
let os_arch = resources::system::os_arch();
let basic = HashMap::from_iter(vec![
("node", sys.host_name().unwrap_or("Unknown".to_string())),
("system", to_title_case(&os_arch.name)),
("system", squire::util::capwords(&os_arch.name, None)),
("architecture", os_arch.architecture),
("uptime", uptime),
("CPU_cores_raw", sys.cpus().len().to_string()
Expand Down
36 changes: 25 additions & 11 deletions src/routes/websocket.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{constant, resources, routes, squire};
use actix_web::rt::time::sleep;
use actix;
use actix_web::{rt, web, Error, HttpRequest, HttpResponse};
use actix_ws::AggregatedMessage;
use fernet::Fernet;
Expand All @@ -13,19 +13,20 @@ use std::time::Duration;
/// # Arguments
///
/// * `request` - A reference to the Actix web `HttpRequest` object.
async fn send_system_resources(mut session: actix_ws::Session) {
async fn send_system_resources(request: HttpRequest, mut session: actix_ws::Session) {
let host = request.connection_info().host().to_string();
loop {
let system_resources = resources::stream::system_resources();
let serialized = serde_json::to_string(&system_resources).unwrap();
match session.text(serialized).await {
Ok(_) => (),
Err(err) => {
log::warn!("Connection {} by the client!", err);
log::info!("Connection from '{}' has been {}", host, err.to_string().to_lowercase());
break;
}
}
// 500ms / 0.5s delay
sleep(Duration::from_secs(1)).await;
rt::time::sleep(Duration::from_secs(1)).await;
}
}

Expand All @@ -49,7 +50,7 @@ async fn send_system_resources(mut session: actix_ws::Session) {
/// * `stream` - A stream of `AggregatedMessage` objects.
async fn receive_messages(
mut session: actix_ws::Session,
mut stream: impl futures::Stream<Item=Result<AggregatedMessage, actix_ws::ProtocolError>> + Unpin
mut stream: impl futures::Stream<Item=Result<AggregatedMessage, actix_ws::ProtocolError>> + Unpin,
) {
while let Some(msg) = stream.next().await {
match msg {
Expand All @@ -70,6 +71,20 @@ async fn receive_messages(
}
}

/// Handles the session by closing it after a certain duration.
///
/// # Arguments
///
/// * `session` - A reference to the Actix web `Session` object.
/// * `duration` - Duration in seconds to keep the session alive.
async fn session_handler(session: actix_ws::Session, duration: i64) {
let session = session.clone();
actix::spawn(async move {
rt::time::sleep(Duration::from_secs(duration as u64)).await;
let _ = session.close(None).await;
});
}

/// Handles the WebSocket endpoint for system resources.
///
/// # Arguments
Expand Down Expand Up @@ -100,17 +115,16 @@ async fn echo(
Ok(result) => result,
Err(_) => {
return Ok(HttpResponse::ServiceUnavailable().finish());
},
}
};
// todo: implement a session timeout here
let stream = stream
.aggregate_continuations();
rt::spawn(async move {
log::warn!("Connection established");
let send_task = send_system_resources(session.clone());
let receive_task = receive_messages(session, stream);
future::join(send_task, receive_task).await;
let send_task = send_system_resources(request.clone(), session.clone());
let receive_task = receive_messages(session.clone(), stream);
let session_task = session_handler(session.clone(), config.session_duration);
future::join3(send_task, receive_task, session_task).await;
});
// respond immediately with response connected to WS session
Ok(response)
}
27 changes: 27 additions & 0 deletions src/squire/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,30 @@ pub fn run_command(command: &str, args: &[&str]) -> Result<String, String> {
}
}
}

/// Function to capitalize the first letter of each word in a string.
///
/// # Arguments
///
/// * `s` - The string to capitalize
/// * `sep` - The separator to split the string
///
/// # Returns
///
/// A `String` containing the capitalized string
pub fn capwords(string: &str, sep: Option<&str>) -> String {
let separator = sep.unwrap_or(" ");
let mut result = Vec::new();

for word in string.split(separator) {
let mut chars = word.chars();
if let Some(first) = chars.next() {
let capitalized_word = first.to_uppercase().collect::<String>() + chars.as_str();
result.push(capitalized_word);
} else {
result.push(String::new());
}
}

result.join(separator)
}
4 changes: 2 additions & 2 deletions src/templates/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::sync::Arc;
use minijinja::{value::Value};
use inflector::cases::titlecase::to_title_case;
use crate::squire;

/// Index page template that is served as HTML response for the root endpoint.
mod index;
Expand Down Expand Up @@ -44,7 +44,7 @@ fn capwords_filter(value: Value) -> Result<Value, minijinja::Error> {
Ok(Value::from(result))
} else {
let result = val.replace("_", " ");
Ok(Value::from(to_title_case(&result)))
Ok(Value::from(squire::util::capwords(&result, None)))
}
} else {
panic!("capwords filter only works with strings");
Expand Down

0 comments on commit f5ed531

Please sign in to comment.