From 66572c0e1f019575fe35635a34401b15fe5d8346 Mon Sep 17 00:00:00 2001 From: Rafael Garcia Date: Tue, 13 Jan 2026 12:59:02 -0500 Subject: [PATCH] Add /json/list and /json/new CDP proxy endpoints Proxy these Chrome DevTools Protocol JSON endpoints to the upstream Chromium instance: - /json/list - List all browser targets (pages, extensions, workers) - /json/new - Create a new browser target This enables clients to query browser state via CDP without direct access to the internal Chromium port. Useful for verifying extensions are loaded, inspecting open pages, etc. Includes 10-second timeout on upstream requests to prevent hangs. --- server/cmd/api/main.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/server/cmd/api/main.go b/server/cmd/api/main.go index b5db5cf6..a15faa2b 100644 --- a/server/cmd/api/main.go +++ b/server/cmd/api/main.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "io" "log/slog" "net/http" "net/url" @@ -172,6 +173,40 @@ func main() { "webSocketDebuggerUrl": proxyWSURL, }) }) + // Proxy CDP JSON endpoints to upstream Chromium DevTools + cdpProxyHandler := func(path string) http.HandlerFunc { + client := &http.Client{Timeout: 10 * time.Second} + return func(w http.ResponseWriter, r *http.Request) { + current := upstreamMgr.Current() + if current == "" { + http.Error(w, "upstream not ready", http.StatusServiceUnavailable) + return + } + upstreamURL, err := url.Parse(current) + if err != nil { + http.Error(w, "invalid upstream URL", http.StatusInternalServerError) + return + } + httpURL := &url.URL{ + Scheme: "http", + Host: upstreamURL.Host, + Path: path, + RawQuery: r.URL.RawQuery, + } + resp, err := client.Get(httpURL.String()) + if err != nil { + slogger.Error("failed to proxy CDP endpoint", "path", path, "err", err) + http.Error(w, "failed to reach upstream", http.StatusBadGateway) + return + } + defer resp.Body.Close() + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(resp.StatusCode) + io.Copy(w, resp.Body) + } + } + rDevtools.Get("/json/list", cdpProxyHandler("/json/list")) + rDevtools.Get("/json/new", cdpProxyHandler("/json/new")) rDevtools.Get("/*", func(w http.ResponseWriter, r *http.Request) { devtoolsproxy.WebSocketProxyHandler(upstreamMgr, slogger, config.LogCDPMessages, stz).ServeHTTP(w, r) })