From 280a579e595006062b143333fe7d9f657afa9625 Mon Sep 17 00:00:00 2001 From: Tyler Longwell Date: Fri, 8 May 2026 22:49:42 -0400 Subject: [PATCH] fix: resolve media proxy relay URL dynamically per-request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The axum media proxy was baking in the relay base URL at startup, so switching workspaces in the GUI left the proxy pointed at the old relay — resulting in 404s and broken images. Now reads relay_url_override from AppState on every request, matching the pattern already used by handle_sprout_media. Fixes broken images when switching between relays. --- desktop/src-tauri/src/lib.rs | 3 +-- desktop/src-tauri/src/media_proxy.rs | 14 ++++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index 2ffbfd88f..34aa64436 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -376,10 +376,9 @@ pub fn run() { // client so WARP tunnelling applies. The port is stored in AppState // and exposed to the frontend via the `get_media_proxy_port` command. let proxy_client = state.http_client.clone(); - let proxy_base_url = relay::relay_api_base_url_with_override(&state); let proxy_handle = app_handle.clone(); tauri::async_runtime::spawn(async move { - let port = media_proxy::spawn_media_proxy(proxy_client, proxy_base_url).await; + let port = media_proxy::spawn_media_proxy(proxy_client, proxy_handle.clone()).await; let state = proxy_handle.state::(); state .media_proxy_port diff --git a/desktop/src-tauri/src/media_proxy.rs b/desktop/src-tauri/src/media_proxy.rs index bf224829b..75402dc45 100644 --- a/desktop/src-tauri/src/media_proxy.rs +++ b/desktop/src-tauri/src/media_proxy.rs @@ -7,7 +7,7 @@ use axum::{ Router, }; use futures_util::TryStreamExt; -use tauri::http; +use tauri::{http, Manager}; use tokio::net::TcpListener; use crate::app_state::AppState; @@ -22,7 +22,7 @@ const MAX_PROXY_RESPONSE: u64 = 20 * 1024 * 1024; #[derive(Clone)] struct ProxyState { client: reqwest::Client, - base_url: String, + app_handle: tauri::AppHandle, } async fn proxy_handler(AxumState(state): AxumState, req: Request) -> Response { @@ -44,8 +44,10 @@ async fn proxy_handler(AxumState(state): AxumState, req: Request) -> .map(|pq| pq.as_str()) .unwrap_or("/"); - // Strip the /media/ prefix check — we only mount on /media/ - let upstream_url = format!("{}{path_and_query}", state.base_url); + // Resolve relay URL dynamically so workspace switches take effect immediately. + let app_state = state.app_handle.state::(); + let base_url = relay::relay_api_base_url_with_override(&app_state); + let upstream_url = format!("{base_url}{path_and_query}"); let has_range = req.headers().contains_key("range"); @@ -111,10 +113,10 @@ async fn proxy_handler(AxumState(state): AxumState, req: Request) -> /// Spawn a localhost HTTP proxy that streams media via reqwest, avoiding the /// Tauri protocol handler's requirement to buffer the entire response into /// `Vec`. Returns the OS-assigned port. -pub async fn spawn_media_proxy(http_client: reqwest::Client, base_url: String) -> u16 { +pub async fn spawn_media_proxy(http_client: reqwest::Client, app_handle: tauri::AppHandle) -> u16 { let proxy_state = ProxyState { client: http_client, - base_url, + app_handle, }; let app = Router::new()