diff options
| author | Aram Drevekenin <aram@poor.dev> | 2026-01-21 10:53:18 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-21 10:53:18 +0100 |
| commit | d8e16ef9fe8c79a542fda969ee53f3e7cb9f837d (patch) | |
| tree | 2cf78a4d35f7ba28a3d970432cb2780b77bf985a | |
| parent | Fix tiled new pane borderless (#4618) (diff) | |
| download | sl0ppij-d8e16ef9fe8c79a542fda969ee53f3e7cb9f837d.tar.gz sl0ppij-d8e16ef9fe8c79a542fda969ee53f3e7cb9f837d.tar.xz sl0ppij-d8e16ef9fe8c79a542fda969ee53f3e7cb9f837d.zip | |
Fix query webserver from IPC rather than HTTPS (#4620)
* move webserver querying from http to ipc
* rustfmt
* fix no web build
* rustfmt
* add pr
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | zellij-client/src/web_client/ipc_listener.rs | 55 | ||||
| -rw-r--r-- | zellij-client/src/web_client/mod.rs | 12 | ||||
| -rw-r--r-- | zellij-client/src/web_client/unit/web_client_tests.rs | 32 | ||||
| -rw-r--r-- | zellij-server/src/background_jobs.rs | 128 | ||||
| -rw-r--r-- | zellij-utils/assets/prost_web_server/web_server_contract.rs | 39 | ||||
| -rw-r--r-- | zellij-utils/src/shared.rs | 17 | ||||
| -rw-r--r-- | zellij-utils/src/web_server_commands.rs | 60 | ||||
| -rw-r--r-- | zellij-utils/src/web_server_contract/protobuf_conversion.rs | 52 | ||||
| -rw-r--r-- | zellij-utils/src/web_server_contract/web_server_commands.proto | 19 |
10 files changed, 316 insertions, 99 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index e4906973..916215ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) * fix: properly center floating panes started with `--floating` when explicit width/height is provided (https://github.com/zellij-org/zellij/pull/4607) * fix: allow specifying "0%" coordinates when opening panes wit "zellij run --floating" (https://github.com/zellij-org/zellij/pull/4609) * feat: allow opening panes as `borderless` or toggling/changing the borderless status of existing panes (https://github.com/zellij-org/zellij/pull/4615 and https://github.com/zellij-org/zellij/pull/4618) +* fix: query webserver through ipc rather than https (https://github.com/zellij-org/zellij/pull/4620) ## [0.43.1] - 2025-08-08 diff --git a/zellij-client/src/web_client/ipc_listener.rs b/zellij-client/src/web_client/ipc_listener.rs index ebc8e150..62344ba8 100644 --- a/zellij-client/src/web_client/ipc_listener.rs +++ b/zellij-client/src/web_client/ipc_listener.rs @@ -1,10 +1,12 @@ use axum_server::Handle; -use tokio::io::AsyncReadExt; +use std::net::IpAddr; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::{UnixListener, UnixStream}; use zellij_utils::consts::WEBSERVER_SOCKET_PATH; use zellij_utils::prost::Message; -use zellij_utils::web_server_commands::InstructionForWebServer; +use zellij_utils::web_server_commands::{InstructionForWebServer, VersionInfo, WebServerResponse}; use zellij_utils::web_server_contract::web_server_contract::InstructionForWebServer as ProtoInstructionForWebServer; +use zellij_utils::web_server_contract::web_server_contract::WebServerResponse as ProtoWebServerResponse; pub async fn create_webserver_receiver( id: &str, @@ -43,23 +45,48 @@ pub async fn receive_webserver_instruction( .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)) } -pub async fn listen_to_web_server_instructions(server_handle: Handle, id: &str) { +pub async fn send_webserver_response( + sender: &mut UnixStream, + response: WebServerResponse, +) -> std::io::Result<()> { + let proto_response: ProtoWebServerResponse = response.into(); + let encoded = proto_response.encode_to_vec(); + let len = encoded.len() as u32; + + sender.write_all(&len.to_le_bytes()).await?; + sender.write_all(&encoded).await?; + sender.flush().await?; + + Ok(()) +} + +pub async fn listen_to_web_server_instructions( + server_handle: Handle, + id: &str, + web_server_ip: IpAddr, + web_server_port: u16, +) { loop { let receiver = create_webserver_receiver(id).await; match receiver { - Ok(mut receiver) => { - match receive_webserver_instruction(&mut receiver).await { - Ok(instruction) => match instruction { - InstructionForWebServer::ShutdownWebServer => { - server_handle.shutdown(); - break; - }, + Ok(mut receiver) => match receive_webserver_instruction(&mut receiver).await { + Ok(instruction) => match instruction { + InstructionForWebServer::ShutdownWebServer => { + server_handle.shutdown(); + break; }, - Err(e) => { - log::error!("Failed to process web server instruction: {}", e); - // Continue loop to recreate receiver and try again + InstructionForWebServer::QueryVersion => { + let response = WebServerResponse::Version(VersionInfo { + version: zellij_utils::consts::VERSION.to_string(), + ip: web_server_ip.to_string(), + port: web_server_port, + }); + let _ = send_webserver_response(&mut receiver, response).await; }, - } + }, + Err(e) => { + log::error!("Failed to process web server instruction: {}", e); + }, }, Err(e) => { log::error!("Failed to listen to ipc channel: {}", e); diff --git a/zellij-client/src/web_client/mod.rs b/zellij-client/src/web_client/mod.rs index f3e04422..02c9399f 100644 --- a/zellij-client/src/web_client/mod.rs +++ b/zellij-client/src/web_client/mod.rs @@ -157,6 +157,8 @@ pub fn start_web_client( tls_config, None, None, + web_server_ip, + web_server_port, )); } @@ -168,6 +170,8 @@ pub async fn serve_web_client( rustls_config: Option<RustlsConfig>, session_manager: Option<Arc<dyn SessionManager>>, client_os_api_factory: Option<Arc<dyn ClientOsApiFactory>>, + web_server_ip: IpAddr, + web_server_port: u16, ) { let Some(config_file_path) = config_file_path.or_else(|| Config::default_config_file_path()) else { @@ -204,7 +208,13 @@ pub async fn serve_web_client( tokio::spawn({ let server_handle = server_handle.clone(); async move { - listen_to_web_server_instructions(server_handle, &format!("{}", id)).await; + listen_to_web_server_instructions( + server_handle, + &format!("{}", id), + web_server_ip, + web_server_port, + ) + .await; } }); diff --git a/zellij-client/src/web_client/unit/web_client_tests.rs b/zellij-client/src/web_client/unit/web_client_tests.rs index 087c2d3b..15a45efa 100644 --- a/zellij-client/src/web_client/unit/web_client_tests.rs +++ b/zellij-client/src/web_client/unit/web_client_tests.rs @@ -88,6 +88,8 @@ mod web_client_tests { None, Some(session_manager), Some(client_os_api_factory), + addr.ip(), + port, )); wait_for_server(port, Duration::from_secs(5)) @@ -147,6 +149,8 @@ mod web_client_tests { None, Some(session_manager), Some(client_os_api_factory), + addr.ip(), + port, ) .await; }); @@ -216,6 +220,8 @@ mod web_client_tests { None, Some(session_manager), Some(client_os_api_factory), + addr.ip(), + port, ) .await; }); @@ -281,6 +287,8 @@ mod web_client_tests { None, Some(session_manager), Some(client_os_api_factory), + addr.ip(), + port, ) .await; }); @@ -480,6 +488,8 @@ mod web_client_tests { None, Some(session_manager), Some(client_os_api_factory), + addr.ip(), + port, ) .await; }); @@ -528,6 +538,8 @@ mod web_client_tests { None, Some(session_manager), Some(client_os_api_factory), + addr.ip(), + port, ) .await; }); @@ -588,6 +600,8 @@ mod web_client_tests { None, Some(session_manager), Some(client_os_api_factory), + addr.ip(), + port, ) .await; }); @@ -733,6 +747,8 @@ mod web_client_tests { None, Some(session_manager), Some(client_os_api_factory), + addr.ip(), + port, ) .await; }); @@ -905,6 +921,8 @@ mod web_client_tests { None, Some(session_manager), Some(client_os_api_factory), + addr.ip(), + port, ) .await; }); @@ -1049,6 +1067,8 @@ mod web_client_tests { None, Some(session_manager), Some(client_os_api_factory), + addr.ip(), + port, ) .await; }); @@ -1166,6 +1186,7 @@ mod web_client_tests { let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); let port = addr.port(); + let ip = addr.ip(); let temp_config_path = std::env::temp_dir().join("test_config.kdl"); let server_handle = tokio::spawn(async move { @@ -1177,6 +1198,8 @@ mod web_client_tests { None, Some(mock_session_manager), Some(mock_os_api_factory), + ip, + port, ) .await; }); @@ -1263,6 +1286,7 @@ mod web_client_tests { let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); let port = addr.port(); + let ip = addr.ip(); let temp_config_path = std::env::temp_dir().join("test_config.kdl"); let server_handle = tokio::spawn(async move { @@ -1274,6 +1298,8 @@ mod web_client_tests { None, Some(mock_session_manager), Some(mock_os_api_factory), + ip, + port, ) .await; }); @@ -1436,6 +1462,7 @@ mod web_client_tests { let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); let port = addr.port(); + let ip = addr.ip(); let temp_config_path = std::env::temp_dir().join("test_config.kdl"); let server_handle = tokio::spawn(async move { @@ -1447,6 +1474,8 @@ mod web_client_tests { None, Some(mock_session_manager), Some(mock_os_api_factory), + ip, + port, ) .await; }); @@ -1544,6 +1573,7 @@ mod web_client_tests { let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); let port = addr.port(); + let ip = addr.ip(); let temp_config_path = std::env::temp_dir().join("test_config.kdl"); let server_handle = tokio::spawn(async move { @@ -1555,6 +1585,8 @@ mod web_client_tests { None, Some(mock_session_manager), Some(mock_os_api_factory), + ip, + port, ) .await; }); diff --git a/zellij-server/src/background_jobs.rs b/zellij-server/src/background_jobs.rs index d91a80a4..22828e15 100644 --- a/zellij-server/src/background_jobs.rs +++ b/zellij-server/src/background_jobs.rs @@ -6,6 +6,13 @@ use zellij_utils::consts::{ use zellij_utils::data::{Event, HttpVerb, SessionInfo, WebServerStatus}; use zellij_utils::errors::{prelude::*, BackgroundJobContext, ContextType}; use zellij_utils::input::layout::RunPlugin; +use zellij_utils::shared::parse_base_url; + +#[cfg(feature = "web_server_capability")] +use zellij_utils::web_server_commands::{ + discover_webserver_sockets, query_webserver_with_response, InstructionForWebServer, + WebServerResponse, +}; use isahc::prelude::*; use isahc::AsyncReadResponseExt; @@ -382,85 +389,22 @@ pub(crate) fn background_jobs_main( }); }, BackgroundJob::QueryZellijWebServerStatus => { - if !cfg!(feature = "web_server_capability") { - // no web server capability, no need to query - continue; - } - + #[cfg(feature = "web_server_capability")] task::spawn({ - let http_client = http_client.clone(); let senders = bus.senders.clone(); let web_server_base_url = web_server_base_url.clone(); async move { - async fn web_request( - http_client: HttpClient, - web_server_base_url: &str, - ) -> Result< - (u16, Vec<u8>), // status_code, body - isahc::Error, - > { - let request = - Request::get(format!("{}/info/version", web_server_base_url,)); - let req = request.body(())?; - let mut res = http_client.send_async(req).await?; - - let status_code = res.status(); - let body = res.bytes().await?; - Ok((status_code.as_u16(), body)) - } - let Some(http_client) = http_client else { - log::error!("Cannot perform http request, likely due to a misconfigured http client"); - return; - }; + let status = task::spawn_blocking(move || { + query_webserver_via_ipc(&web_server_base_url) + }) + .await + .unwrap_or(WebServerStatus::Offline); - let http_client = http_client.clone(); - match web_request(http_client, &web_server_base_url).await { - Ok((status, body)) => { - if status == 200 && &body == VERSION.as_bytes() { - // online - let _ = - senders.send_to_plugin(PluginInstruction::Update(vec![( - None, - None, - Event::WebServerStatus(WebServerStatus::Online( - web_server_base_url.clone(), - )), - )])); - } else if status == 200 { - let _ = - senders.send_to_plugin(PluginInstruction::Update(vec![( - None, - None, - Event::WebServerStatus( - WebServerStatus::DifferentVersion( - String::from_utf8_lossy(&body).to_string(), - ), - ), - )])); - } else { - // offline/error - let _ = - senders.send_to_plugin(PluginInstruction::Update(vec![( - None, - None, - Event::WebServerStatus(WebServerStatus::Offline), - )])); - } - }, - Err(e) => { - if e.kind() == isahc::error::ErrorKind::ConnectionFailed { - let _ = - senders.send_to_plugin(PluginInstruction::Update(vec![( - None, - None, - Event::WebServerStatus(WebServerStatus::Offline), - )])); - } else { - // no-op - otherwise we'll get errors if we were mid-request - // (eg. when the server was shut down by a user action) - } - }, - } + let _ = senders.send_to_plugin(PluginInstruction::Update(vec![( + None, + None, + Event::WebServerStatus(status), + )])); } }); }, @@ -678,3 +622,39 @@ fn find_resurrectable_sessions( }, } } + +#[cfg(feature = "web_server_capability")] +fn query_webserver_via_ipc(web_server_base_url: &str) -> Result<WebServerStatus> { + let expected_addr = + parse_base_url(web_server_base_url).context("Failed to parse web server base URL")?; + + let sockets = discover_webserver_sockets().context("Failed to discover web server sockets")?; + + if sockets.is_empty() { + return Ok(WebServerStatus::Offline); + } + + for socket_path in sockets { + let path_str = socket_path.to_str().unwrap_or(""); + + match query_webserver_with_response(path_str, InstructionForWebServer::QueryVersion, 500) { + Ok(WebServerResponse::Version(info)) => { + let matches_expected = + info.ip == expected_addr.ip && info.port == expected_addr.port; + + if !matches_expected { + continue; + } + + if info.version == VERSION { + return Ok(WebServerStatus::Online(web_server_base_url.to_string())); + } else { + return Ok(WebServerStatus::DifferentVersion(info.version)); + } + }, + Err(_) => continue, + } + } + + Ok(WebServerStatus::Offline) +} diff --git a/zellij-utils/assets/prost_web_server/web_server_contract.rs b/zellij-utils/assets/prost_web_server/web_server_contract.rs index c2e4dda5..05d9897b 100644 --- a/zellij-utils/assets/prost_web_server/web_server_contract.rs +++ b/zellij-utils/assets/prost_web_server/web_server_contract.rs @@ -1,7 +1,7 @@ #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct InstructionForWebServer { - #[prost(oneof="instruction_for_web_server::Instruction", tags="1")] + #[prost(oneof="instruction_for_web_server::Instruction", tags="1, 2")] pub instruction: ::core::option::Option<instruction_for_web_server::Instruction>, } /// Nested message and enum types in `InstructionForWebServer`. @@ -9,11 +9,13 @@ pub mod instruction_for_web_server { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Instruction { - /// Future commands can be added here - /// RestartWebServerMsg restart_web_server = 2; - /// ReloadConfigMsg reload_config = 3; #[prost(message, tag="1")] ShutdownWebServer(super::ShutdownWebServerMsg), + /// Future commands can be added here + /// RestartWebServerMsg restart_web_server = 3; + /// ReloadConfigMsg reload_config = 4; + #[prost(message, tag="2")] + QueryVersion(super::QueryVersionMsg), } } /// Empty for now, but allows for future parameters like graceful timeout @@ -21,3 +23,32 @@ pub mod instruction_for_web_server { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ShutdownWebServerMsg { } +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryVersionMsg { +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct WebServerResponse { + #[prost(oneof="web_server_response::Response", tags="1")] + pub response: ::core::option::Option<web_server_response::Response>, +} +/// Nested message and enum types in `WebServerResponse`. +pub mod web_server_response { + #[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Response { + #[prost(message, tag="1")] + Version(super::VersionResponseMsg), + } +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct VersionResponseMsg { + #[prost(string, tag="1")] + pub version: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub ip: ::prost::alloc::string::String, + #[prost(uint32, tag="3")] + pub port: u32, +} diff --git a/zellij-utils/src/shared.rs b/zellij-utils/src/shared.rs index 759bc0f4..5273c205 100644 --- a/zellij-utils/src/shared.rs +++ b/zellij-utils/src/shared.rs @@ -5,6 +5,7 @@ use std::{iter, str::from_utf8}; use crate::data::{Palette, PaletteColor, PaletteSource, ThemeHue}; use crate::envs::get_session_name; +use crate::errors::prelude::*; use crate::input::options::Options; use colorsys::{Ansi256, Rgb}; use strip_ansi_escapes::strip; @@ -207,3 +208,19 @@ pub fn web_server_base_url_from_config(config_options: Options) -> String { enforce_https_for_localhost, ) } + +pub struct ServerAddress { + pub ip: String, + pub port: u16, +} + +pub fn parse_base_url(url: &str) -> Result<ServerAddress> { + let url = url::Url::parse(url)?; + let ip = url + .host_str() + .ok_or_else(|| anyhow!("No host in URL"))? + .to_string(); + let port = url.port().ok_or_else(|| anyhow!("No port in URL"))?; + + Ok(ServerAddress { ip, port }) +} diff --git a/zellij-utils/src/web_server_commands.rs b/zellij-utils/src/web_server_commands.rs index a1bcf885..3b5c4065 100644 --- a/zellij-utils/src/web_server_commands.rs +++ b/zellij-utils/src/web_server_commands.rs @@ -1,12 +1,14 @@ use crate::consts::WEBSERVER_SOCKET_PATH; use crate::errors::prelude::*; use crate::web_server_contract::web_server_contract::InstructionForWebServer as ProtoInstructionForWebServer; +use crate::web_server_contract::web_server_contract::WebServerResponse as ProtoWebServerResponse; use interprocess::local_socket::LocalSocketStream; use prost::Message; use serde::{Deserialize, Serialize}; use std::fs; -use std::io::{BufWriter, Write}; +use std::io::{BufWriter, Read, Write}; use std::os::unix::fs::FileTypeExt; +use std::path::PathBuf; pub fn shutdown_all_webserver_instances() -> Result<()> { let entries = fs::read_dir(&*WEBSERVER_SOCKET_PATH)?; @@ -42,6 +44,19 @@ pub fn shutdown_all_webserver_instances() -> Result<()> { #[derive(Serialize, Deserialize, Debug, Clone)] pub enum InstructionForWebServer { ShutdownWebServer, + QueryVersion, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct VersionInfo { + pub version: String, + pub ip: String, + pub port: u16, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub enum WebServerResponse { + Version(VersionInfo), } pub fn create_webserver_sender(path: &str) -> Result<BufWriter<LocalSocketStream>> { @@ -65,3 +80,46 @@ pub fn send_webserver_instruction( sender.flush()?; Ok(()) } + +pub fn discover_webserver_sockets() -> Result<Vec<PathBuf>> { + let mut sockets = Vec::new(); + + if !WEBSERVER_SOCKET_PATH.exists() { + return Ok(sockets); + } + + for entry in fs::read_dir(&*WEBSERVER_SOCKET_PATH)? { + let entry = entry?; + let path = entry.path(); + + if entry.metadata()?.file_type().is_socket() { + sockets.push(path); + } + } + + Ok(sockets) +} + +pub fn query_webserver_with_response( + path: &str, + instruction: InstructionForWebServer, + _timeout_ms: u64, +) -> Result<WebServerResponse> { + let mut sender = create_webserver_sender(path)?; + send_webserver_instruction(&mut sender, instruction)?; + + let stream = sender.into_inner()?; + receive_webserver_response(stream) +} + +fn receive_webserver_response(mut stream: LocalSocketStream) -> Result<WebServerResponse> { + let mut len_bytes = [0u8; 4]; + stream.read_exact(&mut len_bytes)?; + let len = u32::from_le_bytes(len_bytes) as usize; + + let mut buffer = vec![0u8; len]; + stream.read_exact(&mut buffer)?; + + let proto_response = ProtoWebServerResponse::decode(&buffer[..])?; + proto_response.try_into() +} diff --git a/zellij-utils/src/web_server_contract/protobuf_conversion.rs b/zellij-utils/src/web_server_contract/protobuf_conversion.rs index 7a89f600..c5f5f496 100644 --- a/zellij-utils/src/web_server_contract/protobuf_conversion.rs +++ b/zellij-utils/src/web_server_contract/protobuf_conversion.rs @@ -1,8 +1,11 @@ use crate::errors::prelude::*; -use crate::web_server_commands::InstructionForWebServer as RustInstructionForWebServer; +use crate::web_server_commands::{ + InstructionForWebServer as RustInstructionForWebServer, VersionInfo, WebServerResponse, +}; use crate::web_server_contract::web_server_contract::{ - instruction_for_web_server, InstructionForWebServer as ProtoInstructionForWebServer, - ShutdownWebServerMsg, + instruction_for_web_server, web_server_response, + InstructionForWebServer as ProtoInstructionForWebServer, QueryVersionMsg, ShutdownWebServerMsg, + VersionResponseMsg, WebServerResponse as ProtoWebServerResponse, }; // Convert Rust InstructionForWebServer to protobuf @@ -12,6 +15,9 @@ impl From<RustInstructionForWebServer> for ProtoInstructionForWebServer { RustInstructionForWebServer::ShutdownWebServer => { instruction_for_web_server::Instruction::ShutdownWebServer(ShutdownWebServerMsg {}) }, + RustInstructionForWebServer::QueryVersion => { + instruction_for_web_server::Instruction::QueryVersion(QueryVersionMsg {}) + }, }; ProtoInstructionForWebServer { @@ -29,7 +35,47 @@ impl TryFrom<ProtoInstructionForWebServer> for RustInstructionForWebServer { Some(instruction_for_web_server::Instruction::ShutdownWebServer(_)) => { Ok(RustInstructionForWebServer::ShutdownWebServer) }, + Some(instruction_for_web_server::Instruction::QueryVersion(_)) => { + Ok(RustInstructionForWebServer::QueryVersion) + }, None => Err(anyhow!("Missing instruction in InstructionForWebServer")), } } } + +// Convert Rust WebServerResponse to protobuf +impl From<WebServerResponse> for ProtoWebServerResponse { + fn from(response: WebServerResponse) -> Self { + let response = match response { + WebServerResponse::Version(version_info) => { + web_server_response::Response::Version(VersionResponseMsg { + version: version_info.version, + ip: version_info.ip, + port: version_info.port as u32, + }) + }, + }; + + ProtoWebServerResponse { + response: Some(response), + } + } +} + +// Convert protobuf WebServerResponse to Rust +impl TryFrom<ProtoWebServerResponse> for WebServerResponse { + type Error = anyhow::Error; + + fn try_from(proto_response: ProtoWebServerResponse) -> Result<Self> { + match proto_response.response { + Some(web_server_response::Response::Version(version_msg)) => { + Ok(WebServerResponse::Version(VersionInfo { + version: version_msg.version, + ip: version_msg.ip, + port: version_msg.port as u16, + })) + }, + None => Err(anyhow!("Missing response in WebServerResponse")), + } + } +} diff --git a/zellij-utils/src/web_server_contract/web_server_commands.proto b/zellij-utils/src/web_server_contract/web_server_commands.proto index f8db28f9..dd1d7ae4 100644 --- a/zellij-utils/src/web_server_contract/web_server_commands.proto +++ b/zellij-utils/src/web_server_contract/web_server_commands.proto @@ -4,12 +4,27 @@ package web_server_contract; message InstructionForWebServer { oneof instruction { ShutdownWebServerMsg shutdown_web_server = 1; + QueryVersionMsg query_version = 2; // Future commands can be added here - // RestartWebServerMsg restart_web_server = 2; - // ReloadConfigMsg reload_config = 3; + // RestartWebServerMsg restart_web_server = 3; + // ReloadConfigMsg reload_config = 4; } } message ShutdownWebServerMsg { // Empty for now, but allows for future parameters like graceful timeout +} + +message QueryVersionMsg {} + +message WebServerResponse { + oneof response { + VersionResponseMsg version = 1; + } +} + +message VersionResponseMsg { + string version = 1; + string ip = 2; + uint32 port = 3; }
\ No newline at end of file |
