This is an automated email from the ASF dual-hosted git repository.

gkoszyk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git


The following commit(s) were added to refs/heads/master by this push:
     new d6a6d4ffe feat(server): add http.web_ui config option to control 
embedded Web UI (#2494)
d6a6d4ffe is described below

commit d6a6d4ffee0215ba1a7479e55aeb63257911caab
Author: Hubert Gruszecki <[email protected]>
AuthorDate: Wed Dec 17 16:38:23 2025 +0100

    feat(server): add http.web_ui config option to control embedded Web UI 
(#2494)
    
    - Add `web_ui` field to HttpConfig (default: false)
    - Add build.rs verification for web assets when iggy-web feature enabled
    - Log warning at startup if web_ui=true but iggy-web feature not
    compiled
    - Document config option in server.toml
---
 core/configs/server.toml            | 10 +++++
 core/server/build.rs                | 77 +++++++++++++++++++++++++++----------
 core/server/src/configs/defaults.rs |  1 +
 core/server/src/configs/displays.rs |  3 +-
 core/server/src/configs/http.rs     |  1 +
 core/server/src/http/http_server.rs | 11 +++++-
 6 files changed, 81 insertions(+), 22 deletions(-)

diff --git a/core/configs/server.toml b/core/configs/server.toml
index 9e075eff4..d795de0a9 100644
--- a/core/configs/server.toml
+++ b/core/configs/server.toml
@@ -36,6 +36,16 @@ address = "127.0.0.1:3000"
 # Maximum size of the request body in bytes. For security reasons, the default 
limit is 2 MB.
 max_request_size = "2 MB"
 
+# Enables the embedded Web UI dashboard at '/ui'.
+# When set to `true` and the server is compiled with the 'iggy-web' feature,
+# the Svelte dashboard will be served at the '/ui' endpoint, providing a
+# browser-based interface for managing streams, topics, and viewing messages.
+# If the server is compiled without 'iggy-web' feature and this is set to 
`true`,
+# a warning will be logged at startup but the server will continue to run.
+# `true` enables the embedded Web UI (requires server built with 'iggy-web' 
feature).
+# `false` disables the embedded Web UI (default).
+web_ui = false
+
 # Configuration for Cross-Origin Resource Sharing (CORS).
 [http.cors]
 # Controls whether CORS is enabled for the HTTP server.
diff --git a/core/server/build.rs b/core/server/build.rs
index 03d508966..9256b28e4 100644
--- a/core/server/build.rs
+++ b/core/server/build.rs
@@ -20,31 +20,68 @@ use std::path::PathBuf;
 use std::{env, error};
 use vergen_git2::{BuildBuilder, CargoBuilder, Emitter, Git2Builder, 
RustcBuilder, SysinfoBuilder};
 
+const WEB_ASSETS_PATH: &str = "web/build/static";
+const WEB_INDEX_FILE: &str = "web/build/static/index.html";
+
 fn main() -> Result<(), Box<dyn error::Error>> {
-    if option_env!("IGGY_CI_BUILD") == Some("true") {
-        Emitter::default()
-            .add_instructions(&BuildBuilder::all_build()?)?
-            .add_instructions(&CargoBuilder::all_cargo()?)?
-            .add_instructions(&Git2Builder::all_git()?)?
-            .add_instructions(&RustcBuilder::all_rustc()?)?
-            .add_instructions(&SysinfoBuilder::all_sysinfo()?)?
-            .emit()?;
+    verify_web_assets_if_enabled();
+    emit_vergen_instructions()?;
+    Ok(())
+}
 
-        let workspace_root = 
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..");
+/// Returns the workspace root (iggy/), two levels up from core/server.
+fn workspace_root() -> PathBuf {
+    PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap())
+        .parent()
+        .and_then(|p| p.parent())
+        .expect("server crate must be at core/server within workspace")
+        .to_path_buf()
+}
 
+fn emit_vergen_instructions() -> Result<(), Box<dyn error::Error>> {
+    if option_env!("IGGY_CI_BUILD") != Some("true") {
+        println!("cargo:info=Skipping vergen because IGGY_CI_BUILD is not set 
to 'true'");
+        return Ok(());
+    }
+
+    Emitter::default()
+        .add_instructions(&BuildBuilder::all_build()?)?
+        .add_instructions(&CargoBuilder::all_cargo()?)?
+        .add_instructions(&Git2Builder::all_git()?)?
+        .add_instructions(&RustcBuilder::all_rustc()?)?
+        .add_instructions(&SysinfoBuilder::all_sysinfo()?)?
+        .emit()?;
+
+    let configs_path = workspace_root()
+        .join("core/configs")
+        .canonicalize()
+        .unwrap_or_else(|e| panic!("Failed to canonicalize configs path: 
{e}"));
+
+    println!("cargo:rerun-if-changed={}", configs_path.display());
+    Ok(())
+}
+
+fn verify_web_assets_if_enabled() {
+    if env::var("CARGO_FEATURE_IGGY_WEB").is_err() {
+        return;
+    }
+
+    let assets_dir = workspace_root().join(WEB_ASSETS_PATH);
+    let index_file = workspace_root().join(WEB_INDEX_FILE);
+
+    println!("cargo:rerun-if-changed={}", assets_dir.display());
+
+    if !assets_dir.exists() || !index_file.exists() {
         println!(
-            "cargo:rerun-if-changed={}",
-            workspace_root
-                .join("configs")
-                .canonicalize()
-                .unwrap_or_else(|e| panic!("Failed to canonicalize path, 
error: {e}"))
-                .display()
-        );
-    } else {
-        println!(
-            "cargo:info=Skipping build script because CI environment variable 
IGGY_CI_BUILD is not set to 'true'"
+            "cargo:warning=Web UI assets not found at {}. \
+             To build them, run: npm --prefix web ci && npm --prefix web run 
build:static",
+            assets_dir.display()
         );
+        return;
     }
 
-    Ok(())
+    println!(
+        "cargo:info=Web UI assets verified at {}",
+        assets_dir.display()
+    );
 }
diff --git a/core/server/src/configs/defaults.rs 
b/core/server/src/configs/defaults.rs
index c864618ee..b2d810e1e 100644
--- a/core/server/src/configs/defaults.rs
+++ b/core/server/src/configs/defaults.rs
@@ -190,6 +190,7 @@ impl Default for HttpConfig {
             enabled: SERVER_CONFIG.http.enabled,
             address: SERVER_CONFIG.http.address.parse().unwrap(),
             max_request_size: 
SERVER_CONFIG.http.max_request_size.parse().unwrap(),
+            web_ui: SERVER_CONFIG.http.web_ui,
             cors: HttpCorsConfig::default(),
             jwt: HttpJwtConfig::default(),
             metrics: HttpMetricsConfig::default(),
diff --git a/core/server/src/configs/displays.rs 
b/core/server/src/configs/displays.rs
index e15680608..a3e64bc62 100644
--- a/core/server/src/configs/displays.rs
+++ b/core/server/src/configs/displays.rs
@@ -38,10 +38,11 @@ impl Display for HttpConfig {
     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
         write!(
             f,
-            "{{ enabled: {}, address: {}, max_request_size: {}, cors: {}, jwt: 
{}, metrics: {}, tls: {} }}",
+            "{{ enabled: {}, address: {}, max_request_size: {}, web_ui: {}, 
cors: {}, jwt: {}, metrics: {}, tls: {} }}",
             self.enabled,
             self.address,
             self.max_request_size,
+            self.web_ui,
             self.cors,
             self.jwt,
             self.metrics,
diff --git a/core/server/src/configs/http.rs b/core/server/src/configs/http.rs
index 83552da45..770632170 100644
--- a/core/server/src/configs/http.rs
+++ b/core/server/src/configs/http.rs
@@ -30,6 +30,7 @@ pub struct HttpConfig {
     pub enabled: bool,
     pub address: String,
     pub max_request_size: IggyByteSize,
+    pub web_ui: bool,
     pub cors: HttpCorsConfig,
     pub jwt: HttpJwtConfig,
     pub metrics: HttpMetricsConfig,
diff --git a/core/server/src/http/http_server.rs 
b/core/server/src/http/http_server.rs
index e83c2191d..669ff772c 100644
--- a/core/server/src/http/http_server.rs
+++ b/core/server/src/http/http_server.rs
@@ -118,11 +118,20 @@ pub async fn start_http_server(
     app = app.layer(middleware::from_fn(request_diagnostics));
 
     #[cfg(feature = "iggy-web")]
-    {
+    if config.web_ui {
         app = app.merge(web::router());
         info!("Web UI enabled at /ui");
     }
 
+    #[cfg(not(feature = "iggy-web"))]
+    if config.web_ui {
+        tracing::warn!(
+            "Web UI is enabled in configuration (http.web_ui = true) but the 
server \
+             was not compiled with 'iggy-web' feature. The Web UI will not be 
available. \
+             To enable it, rebuild the server with: cargo build --features 
iggy-web"
+        );
+    }
+
     if !config.tls.enabled {
         let listener = TcpListener::bind(config.address.clone())
             .await

Reply via email to