feat: proxy local service embeds
This commit is contained in:
parent
d460a6e63e
commit
f8a27b8058
57
api/proxy.go
Normal file
57
api/proxy.go
Normal file
@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func NewLocalProxy(target string, prefix string) http.Handler {
|
||||
upstream, err := url.Parse(target)
|
||||
if err != nil {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
})
|
||||
}
|
||||
|
||||
proxy := httputil.NewSingleHostReverseProxy(upstream)
|
||||
originalDirector := proxy.Director
|
||||
proxy.Director = func(r *http.Request) {
|
||||
originalDirector(r)
|
||||
r.URL.Scheme = upstream.Scheme
|
||||
r.URL.Host = upstream.Host
|
||||
r.URL.Path = strings.TrimPrefix(r.URL.Path, prefix)
|
||||
if r.URL.Path == "" {
|
||||
r.URL.Path = "/"
|
||||
}
|
||||
r.Host = upstream.Host
|
||||
}
|
||||
proxy.ModifyResponse = func(resp *http.Response) error {
|
||||
stripFrameBlockingHeaders(resp.Header)
|
||||
return nil
|
||||
}
|
||||
return proxy
|
||||
}
|
||||
|
||||
func stripFrameBlockingHeaders(header http.Header) {
|
||||
header.Del("X-Frame-Options")
|
||||
csp := header.Get("Content-Security-Policy")
|
||||
if csp == "" {
|
||||
return
|
||||
}
|
||||
header.Set("Content-Security-Policy", removeCSPDirective(csp, "frame-ancestors"))
|
||||
}
|
||||
|
||||
func removeCSPDirective(csp string, directive string) string {
|
||||
parts := strings.Split(csp, ";")
|
||||
kept := parts[:0]
|
||||
for _, part := range parts {
|
||||
trimmed := strings.TrimSpace(part)
|
||||
if trimmed == "" || strings.HasPrefix(strings.ToLower(trimmed), directive) {
|
||||
continue
|
||||
}
|
||||
kept = append(kept, trimmed)
|
||||
}
|
||||
return strings.Join(kept, "; ")
|
||||
}
|
||||
@ -29,6 +29,9 @@ func (s *Server) routes() http.Handler {
|
||||
mux.HandleFunc("/health", s.healthHandler)
|
||||
mux.HandleFunc("/services", s.servicesHandler)
|
||||
mux.HandleFunc("/metrics/simple", s.metricsHandler)
|
||||
mux.Handle("/proxy/openclaw/", NewLocalProxy("http://127.0.0.1:18789", "/proxy/openclaw"))
|
||||
mux.Handle("/proxy/vault/", NewLocalProxy("http://127.0.0.1:8200", "/proxy/vault"))
|
||||
mux.Handle("/ui/", NewLocalProxy("http://127.0.0.1:8200", ""))
|
||||
return mux
|
||||
}
|
||||
|
||||
|
||||
@ -48,8 +48,8 @@ export type ServiceDef = NavItem & {
|
||||
|
||||
export const serviceRegistry: ServiceDef[] = [
|
||||
{ id: 'workspace', label: 'Overview', icon: 'home', href: '#workspace', kind: 'internal', group: 0 },
|
||||
{ id: 'openclaw', label: 'OpenClaw', icon: 'claw', href: 'http://127.0.0.1:18789/channels', kind: 'embed', group: 1, port: 18789, match: ['openclaw', 'gateway'], frameMode: 'external' },
|
||||
{ id: 'vault', label: 'Vault Server', icon: 'shield', href: 'http://127.0.0.1:8200/ui/', kind: 'embed', group: 1, port: 8200, match: ['vault'], frameMode: 'external' },
|
||||
{ id: 'openclaw', label: 'OpenClaw', icon: 'claw', href: 'http://127.0.0.1:8788/proxy/openclaw/channels', kind: 'embed', group: 1, port: 18789, match: ['openclaw', 'gateway'] },
|
||||
{ id: 'vault', label: 'Vault Server', icon: 'shield', href: 'http://127.0.0.1:8788/proxy/vault/ui/', kind: 'embed', group: 1, port: 8200, match: ['vault'] },
|
||||
{ id: 'litellm', label: 'LiteLLM Admin UI', icon: 'chart', href: 'http://localhost:4000/ui', kind: 'embed', group: 1, port: 4000, match: ['litellm', 'lite'] },
|
||||
{ id: 'bridge', label: 'Bridge', icon: 'bridge', href: '#bridge', kind: 'internal', group: 2, match: ['bridge'] },
|
||||
{ id: 'runtime', label: 'Runtime', icon: 'cube', href: '#runtime', kind: 'internal', group: 2 },
|
||||
|
||||
Loading…
Reference in New Issue
Block a user