From 58f784c59ce64eb33254f379452af646104b5f8c Mon Sep 17 00:00:00 2001 From: thibaud-lclr Date: Fri, 17 Apr 2026 16:46:40 +0200 Subject: [PATCH] fix(graylog): use filter=streams for relative search --- src-tauri/src/services/graylog_client.rs | 63 +++++++++++++++++++----- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/src-tauri/src/services/graylog_client.rs b/src-tauri/src/services/graylog_client.rs index b0a0ea7..f52e499 100644 --- a/src-tauri/src/services/graylog_client.rs +++ b/src-tauri/src/services/graylog_client.rs @@ -132,18 +132,7 @@ impl GraylogClient { stream_id: Option<&str>, range_seconds: i32, ) -> Result, String> { - let normalized_range = range_seconds.max(60); - let mut url = format!( - "{}/api/search/universal/relative?query={}&range={}&limit=500", - self.base_url, - urlencoding::encode(query), - normalized_range - ); - - if let Some(stream) = stream_id.map(str::trim).filter(|value| !value.is_empty()) { - url.push_str("&streams="); - url.push_str(&urlencoding::encode(stream)); - } + let url = build_search_relative_url(&self.base_url, query, range_seconds, stream_id); let resp = self.send_get(&url).await?; if !resp.status().is_success() { @@ -159,6 +148,29 @@ impl GraylogClient { } } +fn build_search_relative_url( + base_url: &str, + query: &str, + range_seconds: i32, + stream_id: Option<&str>, +) -> String { + let normalized_range = range_seconds.max(60); + let mut url = format!( + "{}/api/search/universal/relative?query={}&range={}&limit=500", + base_url.trim_end_matches('/'), + urlencoding::encode(query), + normalized_range + ); + + if let Some(stream) = stream_id.map(str::trim).filter(|value| !value.is_empty()) { + let filter = format!("streams:{}", stream); + url.push_str("&filter="); + url.push_str(&urlencoding::encode(&filter)); + } + + url +} + fn decode_token_candidate(token: &str) -> Option { if token.is_empty() { return None; @@ -328,4 +340,31 @@ mod tests { let candidates = build_auth_tokens(raw); assert_eq!(candidates, vec![raw.to_string()]); } + + #[test] + fn test_build_search_relative_url_with_stream_uses_filter_param() { + let url = build_search_relative_url( + "https://graylog.example.com/", + "level:<3", + 1800, + Some("000000000000000000000001"), + ); + + assert!(url.contains("/api/search/universal/relative?")); + assert!(url.contains("query=level%3A%3C3")); + assert!(url.contains("range=1800")); + assert!(url.contains( + "filter=streams%3A000000000000000000000001" + )); + assert!(!url.contains("&streams=")); + } + + #[test] + fn test_build_search_relative_url_without_stream_has_no_filter() { + let url = build_search_relative_url("https://graylog.example.com", "*", 30, None); + + assert!(url.contains("query=%2A")); + assert!(url.contains("range=60")); + assert!(!url.contains("filter=")); + } }