Skip to main content

agentmux_srv/server/
host_http.rs

1// Copyright 2026, AgentMux Corp.
2// SPDX-License-Identifier: Apache-2.0
3
4//! POST to the paired CEF host's browser API (`/agentmux/browser/*`).
5
6use axum::http::StatusCode;
7
8use super::HostIpc;
9
10/// `ui_handlers::proxy_to_host_timeout` for a caller that holds the HTTP client rather
11/// than the whole `AppState` (Tower's sampler, `app_api/tower_pane.rs`).
12pub(crate) async fn post_to_host(
13    http_client: &reqwest::Client,
14    host: &HostIpc,
15    route: &str,
16    body: serde_json::Value,
17    timeout: Option<std::time::Duration>,
18) -> Result<serde_json::Value, String> {
19    let url = format!("http://127.0.0.1:{}/agentmux/browser/{route}", host.port);
20    let mut request = http_client
21        .post(&url)
22        .header("Authorization", format!("Bearer {}", host.token))
23        .json(&body);
24    if let Some(t) = timeout {
25        request = request.timeout(t);
26    }
27    let resp = request
28        .send()
29        .await
30        .map_err(|e| format!("proxy to host {route}: {e}"))?;
31    if resp.status() == StatusCode::UNAUTHORIZED {
32        return Err(
33            "host rejected our ipc_token — stale registration after a host restart? \
34             will self-heal on the host's next host_ipc.Register call"
35                .to_string(),
36        );
37    }
38    resp.json::<serde_json::Value>()
39        .await
40        .map_err(|e| format!("parse host {route} response: {e}"))
41}