From 1a6ad9d00e98bd6b268a7d434a7e78a0bb3cce7b Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Wed, 26 Nov 2025 15:22:41 -0800 Subject: [PATCH 1/5] hyperapp: allow accessing IncomingHttpRequest --- src/hyperapp.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/hyperapp.rs b/src/hyperapp.rs index a55e900..79ceb39 100644 --- a/src/hyperapp.rs +++ b/src/hyperapp.rs @@ -72,6 +72,16 @@ pub fn get_server() -> Option<&'static mut HttpServer> { APP_HELPERS.with(|ctx| ctx.borrow().current_server.map(|ptr| unsafe { &mut *ptr })) } +pub fn get_http_request() -> Option { + APP_HELPERS.with(|helpers| { + helpers + .borrow() + .current_http_context + .as_ref() + .map(|ctx| ctx.request.clone()) + }) +} + pub fn get_http_method() -> Option { APP_HELPERS.with(|helpers| { helpers From 2453cc645de1fe999ab7e5a798d7931b3649aed1 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Mon, 1 Dec 2025 21:41:50 -0800 Subject: [PATCH 2/5] http: add ip etc to WebsocketOpen --- src/http/server.rs | 29 ++++++++++++++++++++++++++--- src/hyperapp.rs | 6 ++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/http/server.rs b/src/http/server.rs index 18bb940..943780b 100644 --- a/src/http/server.rs +++ b/src/http/server.rs @@ -20,6 +20,8 @@ pub enum HttpServerRequest { WebSocketOpen { path: String, channel_id: u32, + #[serde(default)] + source_socket_addr: Option, }, /// Processes can both SEND and RECEIVE this kind of [`crate::Request`] /// (send as [`HttpServerAction::WebSocketPush`]). @@ -300,6 +302,8 @@ pub struct HttpServer { ws_paths: HashMap, /// A mapping of WebSocket paths to the channels that are open on them. ws_channels: HashMap>, + /// A mapping of WebSocket channel IDs to their client socket addresses. + ws_channel_addrs: HashMap, /// The timeout given for `http-server:distro:sys` to respond to a configuration request. pub timeout: u64, } @@ -451,6 +455,7 @@ impl HttpServer { http_paths: HashMap::new(), ws_paths: HashMap::new(), ws_channels: HashMap::new(), + ws_channel_addrs: HashMap::new(), timeout, } } @@ -983,11 +988,24 @@ impl HttpServer { } /// Handle a WebSocket open event from the HTTP server. - pub fn handle_websocket_open(&mut self, path: &str, channel_id: u32) { + pub fn handle_websocket_open( + &mut self, + path: &str, + channel_id: u32, + source_socket_addr: Option, + ) { self.ws_channels .entry(path.to_string()) .or_insert(HashSet::new()) .insert(channel_id); + if let Some(addr) = source_socket_addr { + self.ws_channel_addrs.insert(channel_id, addr); + } + } + + /// Get the socket address for a WebSocket channel. + pub fn get_ws_channel_addr(&self, channel_id: u32) -> Option<&String> { + self.ws_channel_addrs.get(&channel_id) } /// Handle a WebSocket close event from the HTTP server. @@ -995,6 +1013,7 @@ impl HttpServer { self.ws_channels.iter_mut().for_each(|(_, channels)| { channels.remove(&channel_id); }); + self.ws_channel_addrs.remove(&channel_id); } pub fn parse_request(&self, body: &[u8]) -> Result { @@ -1024,8 +1043,12 @@ impl HttpServer { channel_id, message_type, } => ws_handler(channel_id, message_type, last_blob().unwrap_or_default()), - HttpServerRequest::WebSocketOpen { path, channel_id } => { - self.handle_websocket_open(&path, channel_id); + HttpServerRequest::WebSocketOpen { + path, + channel_id, + source_socket_addr, + } => { + self.handle_websocket_open(&path, channel_id, source_socket_addr); } HttpServerRequest::WebSocketClose(channel_id) => { self.handle_websocket_close(channel_id); diff --git a/src/hyperapp.rs b/src/hyperapp.rs index 79ceb39..105803e 100644 --- a/src/hyperapp.rs +++ b/src/hyperapp.rs @@ -72,6 +72,12 @@ pub fn get_server() -> Option<&'static mut HttpServer> { APP_HELPERS.with(|ctx| ctx.borrow().current_server.map(|ptr| unsafe { &mut *ptr })) } +/// Get the socket address for a WebSocket channel by its ID. +/// Returns None if the channel doesn't exist or has no recorded address. +pub fn get_ws_channel_addr(channel_id: u32) -> Option { + get_server().and_then(|server| server.get_ws_channel_addr(channel_id).cloned()) +} + pub fn get_http_request() -> Option { APP_HELPERS.with(|helpers| { helpers From 41f25ceb30935929416137162eb90f101dc720c5 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Tue, 2 Dec 2025 11:25:26 -0800 Subject: [PATCH 3/5] http: add forwarded_for to WebSocketOpen for proxy IP support --- src/http/server.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/http/server.rs b/src/http/server.rs index 943780b..8255730 100644 --- a/src/http/server.rs +++ b/src/http/server.rs @@ -22,6 +22,9 @@ pub enum HttpServerRequest { channel_id: u32, #[serde(default)] source_socket_addr: Option, + /// IP address from proxy headers (X-Forwarded-For, X-Real-IP, Cf-Connecting-Ip) + #[serde(default)] + forwarded_for: Option, }, /// Processes can both SEND and RECEIVE this kind of [`crate::Request`] /// (send as [`HttpServerAction::WebSocketPush`]). @@ -993,13 +996,16 @@ impl HttpServer { path: &str, channel_id: u32, source_socket_addr: Option, + forwarded_for: Option, ) { self.ws_channels .entry(path.to_string()) .or_insert(HashSet::new()) .insert(channel_id); - if let Some(addr) = source_socket_addr { - self.ws_channel_addrs.insert(channel_id, addr); + // Store the client IP, preferring forwarded_for (from proxy headers) over socket addr + let client_ip = forwarded_for.or(source_socket_addr); + if let Some(ip) = client_ip { + self.ws_channel_addrs.insert(channel_id, ip); } } @@ -1047,8 +1053,9 @@ impl HttpServer { path, channel_id, source_socket_addr, + forwarded_for, } => { - self.handle_websocket_open(&path, channel_id, source_socket_addr); + self.handle_websocket_open(&path, channel_id, source_socket_addr, forwarded_for); } HttpServerRequest::WebSocketClose(channel_id) => { self.handle_websocket_close(channel_id); From ce4ee3d31bf7099330aade12998f3b70f087f689 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Tue, 2 Dec 2025 16:07:48 -0800 Subject: [PATCH 4/5] bump version to 2.3.1 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 84ee5c5..666ab45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "hyperware_process_lib" authors = ["Sybil Technologies AG"] -version = "2.3.0" +version = "2.3.1" edition = "2021" description = "A library for writing Hyperware processes in Rust." homepage = "https://hyperware.ai" From 8dab603eea74a4fff58dcd79a1831178e7b19920 Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Fri, 5 Dec 2025 16:58:10 -0800 Subject: [PATCH 5/5] bump version to 3.0.0 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68139ff..15201fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1617,7 +1617,7 @@ dependencies = [ [[package]] name = "hyperware_process_lib" -version = "2.3.1" +version = "3.0.0" dependencies = [ "alloy", "alloy-primitives", diff --git a/Cargo.toml b/Cargo.toml index 666ab45..77dc266 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "hyperware_process_lib" authors = ["Sybil Technologies AG"] -version = "2.3.1" +version = "3.0.0" edition = "2021" description = "A library for writing Hyperware processes in Rust." homepage = "https://hyperware.ai"