From 1d8a92bf9561d3c42c595e40574df66fd6bef704 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Mon, 17 Aug 2026 10:49:23 -0700 Subject: [PATCH] One 'Executed by' line, first in the timeline --- crates-server/yaak-send-proxy/src/send.rs | 6 ------ packages/platform/src/web/proxy.ts | 18 ++++++++++++++++++ packages/platform/src/web/send.ts | 10 +++++----- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/crates-server/yaak-send-proxy/src/send.rs b/crates-server/yaak-send-proxy/src/send.rs index 882a6270..a8c2c980 100644 --- a/crates-server/yaak-send-proxy/src/send.rs +++ b/crates-server/yaak-send-proxy/src/send.rs @@ -202,12 +202,6 @@ impl PreparedSend { let _ = cancel_tx.send(true); }); - // The first line of what the proxy adds to the timeline says what did the sending, - // so a response's timeline is honest about the hop between the tab and the server. - let _ = event_tx.try_send(HttpResponseEvent::Info(format!( - "Executed by yaak-send-proxy {}", - env!("CARGO_PKG_VERSION") - ))); if self.timeout_capped { let _ = event_tx.try_send(HttpResponseEvent::Info(format!( "Timeout set to {:?} (this proxy's ceiling)", diff --git a/packages/platform/src/web/proxy.ts b/packages/platform/src/web/proxy.ts index a3ecae49..e886c9f4 100644 --- a/packages/platform/src/web/proxy.ts +++ b/packages/platform/src/web/proxy.ts @@ -25,6 +25,24 @@ export function proxySendUrl(): string { return `${proxyBaseUrl()}/v1/http/send`; } +let identity: Promise | null = null; + +/** + * Who does the sending, for the timeline: `yaak-send-proxy 0.1.0 at http://…`. + * Asked of `/v1/health` once per page load; if the proxy can't be reached the + * URL alone is the answer, and the send itself will say why shortly after. + */ +export function proxyIdentity(): Promise { + identity ??= fetch(`${proxyBaseUrl()}/v1/health`) + .then((res) => res.json() as Promise<{ version?: string }>) + .then((health) => `yaak-send-proxy ${health.version ?? ""} at ${proxyBaseUrl()}`.replace(" ", " ")) + .catch(() => { + identity = null; // try again next send + return `send proxy at ${proxyBaseUrl()}`; + }); + return identity; +} + /** * Yield frames from an NDJSON stream as they arrive. A partial trailing line is * held until its newline comes; anything left when the stream ends is dropped, diff --git a/packages/platform/src/web/send.ts b/packages/platform/src/web/send.ts index 66195c41..7b970280 100644 --- a/packages/platform/src/web/send.ts +++ b/packages/platform/src/web/send.ts @@ -33,7 +33,7 @@ import type { } from "@yaakapp-internal/models"; import type { Frame, SendRequest } from "@yaakapp-internal/send-proxy"; import type { WorkerConnection } from "./connection"; -import { proxyBaseUrl, proxySendUrl, readFrames } from "./proxy"; +import { proxyIdentity, proxySendUrl, readFrames } from "./proxy"; /* -------------------------------- shapes --------------------------------- */ @@ -103,12 +103,12 @@ async function runSend( }); await response.patch({ url: prepared.request.url }); + // The first line of the timeline says what did the sending and where. A + // request through a proxy shows a different origin to the server than the + // user's machine, and this is where that should be visible. const timeline = new TimelineWriter(db, response.id, response.workspaceId); + timeline.push([{ type: "info", message: `Executed by ${await proxyIdentity()}` }]); timeline.push(prepared.settingEvents); - // Where the bytes actually left from. A request through a proxy shows a - // different origin to the server than the user's machine, and the timeline - // is where that should be visible. - timeline.push([{ type: "setting", name: "proxy", value: proxyBaseUrl() }]); const body: SendRequest = { request: prepared.request,