mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-02-18 00:17:39 +01:00
fix(ai): allow OpenCode UI to be embedded in iframe
The OpenCode reverse proxy now properly modifies response headers to allow iframe embedding within Pulse's AI panel: - ai_handler.go: Add ModifyResponse to strip X-Frame-Options and modify CSP frame-ancestors from OpenCode's responses - security.go: Skip frame-related security headers for /opencode/ paths since the proxy manages its own headers This fixes the "refused to connect" error when opening the AI sidebar.
This commit is contained in:
@@ -421,6 +421,30 @@ func (h *AIHandler) HandleOpenCodeUI(w http.ResponseWriter, r *http.Request) {
|
||||
req.Host = target.Host
|
||||
}
|
||||
|
||||
// Modify response to allow embedding in iframe
|
||||
// OpenCode sets X-Frame-Options: DENY and CSP frame-ancestors 'none'
|
||||
// which prevents embedding - we need to remove these for the Pulse panel
|
||||
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")
|
||||
|
||||
// Handle multiple CSP headers - get all values, modify, and set back
|
||||
cspHeaders := resp.Header.Values("Content-Security-Policy")
|
||||
if len(cspHeaders) > 0 {
|
||||
// Delete all existing CSP headers
|
||||
resp.Header.Del("Content-Security-Policy")
|
||||
// Add back modified versions
|
||||
for _, csp := range cspHeaders {
|
||||
// Replace frame-ancestors 'none' with 'self' to allow embedding
|
||||
modified := strings.ReplaceAll(csp, "frame-ancestors 'none'", "frame-ancestors 'self'")
|
||||
resp.Header.Add("Content-Security-Policy", modified)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Handle WebSocket upgrades
|
||||
if r.Header.Get("Upgrade") == "websocket" {
|
||||
proxy.ServeHTTP(w, r)
|
||||
|
||||
@@ -409,8 +409,14 @@ func ResetLockout(identifier string) {
|
||||
// SecurityHeadersWithConfig applies security headers with embedding configuration
|
||||
func SecurityHeadersWithConfig(next http.Handler, allowEmbedding bool, allowedOrigins string) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Skip frame-related headers for /opencode/ paths - these are managed by the proxy
|
||||
// The OpenCode proxy modifies headers to allow embedding within Pulse's AI panel
|
||||
isOpenCodePath := strings.HasPrefix(r.URL.Path, "/opencode")
|
||||
|
||||
// Configure clickjacking protection based on embedding settings
|
||||
if allowEmbedding {
|
||||
if isOpenCodePath {
|
||||
// OpenCode proxy manages its own iframe headers
|
||||
} else if allowEmbedding {
|
||||
// When embedding is allowed, don't set X-Frame-Options header
|
||||
// This allows embedding from any origin
|
||||
// Security note: User explicitly enabled this for iframe embedding
|
||||
@@ -436,7 +442,10 @@ func SecurityHeadersWithConfig(next http.Handler, allowEmbedding bool, allowedOr
|
||||
}
|
||||
|
||||
// Add frame-ancestors based on embedding settings
|
||||
if allowEmbedding {
|
||||
// Skip for /opencode/ paths - the proxy manages its own CSP
|
||||
if isOpenCodePath {
|
||||
// OpenCode proxy manages its own CSP headers
|
||||
} else if allowEmbedding {
|
||||
if allowedOrigins != "" {
|
||||
// Parse comma-separated origins and add them to frame-ancestors
|
||||
origins := strings.Split(allowedOrigins, ",")
|
||||
@@ -457,7 +466,10 @@ func SecurityHeadersWithConfig(next http.Handler, allowEmbedding bool, allowedOr
|
||||
cspDirectives = append(cspDirectives, "frame-ancestors 'none'")
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Security-Policy", strings.Join(cspDirectives, "; "))
|
||||
// Only set CSP for non-OpenCode paths (OpenCode proxy manages its own headers)
|
||||
if !isOpenCodePath {
|
||||
w.Header().Set("Content-Security-Policy", strings.Join(cspDirectives, "; "))
|
||||
}
|
||||
|
||||
// Referrer Policy
|
||||
w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")
|
||||
|
||||
Reference in New Issue
Block a user