fix(ai): rewrite OpenCode asset paths for iframe embedding

OpenCode's HTML uses absolute paths like /assets/... for static files.
When embedded in Pulse's iframe, these paths don't go through the
/opencode/ proxy and fail to load.

Modified the proxy's ModifyResponse to rewrite src="/" and href="/"
attributes in HTML responses to include the /opencode/ prefix, ensuring
all assets load correctly through the proxy.
This commit is contained in:
rcourtman
2026-01-14 10:35:37 +00:00
parent 875d244b66
commit 7f9995adf3

View File

@@ -3,6 +3,8 @@ package api
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httputil"
"net/url"
@@ -421,11 +423,11 @@ func (h *AIHandler) HandleOpenCodeUI(w http.ResponseWriter, r *http.Request) {
req.Host = target.Host
}
// Modify response to allow embedding in iframe
// Modify response to allow embedding in iframe and fix asset paths
// OpenCode sets X-Frame-Options: DENY and CSP frame-ancestors 'none'
// which prevents embedding - we need to remove these for the Pulse panel
// Also, OpenCode uses absolute paths for assets which need to be prefixed
proxy.ModifyResponse = func(resp *http.Response) error {
log.Debug().Msg("ModifyResponse called")
// Remove X-Frame-Options to allow iframe embedding
resp.Header.Del("X-Frame-Options")
@@ -442,6 +444,29 @@ func (h *AIHandler) HandleOpenCodeUI(w http.ResponseWriter, r *http.Request) {
}
}
// Rewrite asset paths in HTML responses
// OpenCode uses absolute paths like /assets/... which need to be /opencode/assets/...
contentType := resp.Header.Get("Content-Type")
if strings.Contains(contentType, "text/html") && resp.Body != nil {
body, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return err
}
// Rewrite absolute paths to include /opencode/ prefix
html := string(body)
// Rewrite src="/..." and href="/..." to src="/opencode/..." and href="/opencode/..."
// Be careful not to rewrite already-prefixed paths or external URLs
html = strings.ReplaceAll(html, `src="/`, `src="/opencode/`)
html = strings.ReplaceAll(html, `href="/`, `href="/opencode/`)
// Update response body
resp.Body = io.NopCloser(strings.NewReader(html))
resp.ContentLength = int64(len(html))
resp.Header.Set("Content-Length", fmt.Sprintf("%d", len(html)))
}
return nil
}