feat(launcher): add host overrides for launcher and gateway

This commit is contained in:
lc6464
2026-04-13 17:29:22 +08:00
parent df9124b824
commit 4e977367c2
8 changed files with 323 additions and 13 deletions
+32
View File
@@ -11,6 +11,11 @@ import (
)
func (h *Handler) effectiveLauncherPublic() bool {
if h.serverHostExplicit {
// -host takes precedence over -public and launcher-config public setting.
return false
}
if h.serverPublicExplicit {
return h.serverPublic
}
@@ -23,7 +28,34 @@ func (h *Handler) effectiveLauncherPublic() bool {
return h.serverPublic
}
func canonicalLauncherBindHost(host string) string {
host = strings.TrimSpace(host)
if host == "" || strings.EqualFold(host, "localhost") {
return "127.0.0.1"
}
return host
}
func (h *Handler) launcherAndGatewayBindHostsAligned() bool {
cfg, err := config.LoadConfig(h.configPath)
if err != nil || cfg == nil {
return false
}
// With -host specified, -public is ignored, so launcher's legacy bind host is loopback.
launcherHost := canonicalLauncherBindHost("127.0.0.1")
gatewayHost := canonicalLauncherBindHost(cfg.Gateway.Host)
return launcherHost == gatewayHost
}
func (h *Handler) gatewayHostOverride() string {
if h.serverHostExplicit {
if h.launcherAndGatewayBindHostsAligned() {
return strings.TrimSpace(h.serverHost)
}
return ""
}
if h.effectiveLauncherPublic() {
return "0.0.0.0"
}
+49
View File
@@ -240,3 +240,52 @@ func TestBuildWsURLUsesRequestHostNotGatewayBindLoopback(t *testing.T) {
t.Fatalf("buildWsURL() = %q, want %q", got, "ws://localhost:18800/pico/ws")
}
}
func TestGatewayHostOverrideWithExplicitHostAndAlignedGatewayHost(t *testing.T) {
configPath := filepath.Join(t.TempDir(), "config.json")
writeGatewayHostConfig(t, configPath, "127.0.0.1")
h := NewHandler(configPath)
h.SetServerOptions(18800, false, false, nil)
h.SetServerBindHost("0.0.0.0", true)
if got := h.gatewayHostOverride(); got != "0.0.0.0" {
t.Fatalf("gatewayHostOverride() = %q, want %q", got, "0.0.0.0")
}
}
func TestGatewayHostOverrideWithExplicitHostAndMismatchedGatewayHost(t *testing.T) {
configPath := filepath.Join(t.TempDir(), "config.json")
writeGatewayHostConfig(t, configPath, "0.0.0.0")
h := NewHandler(configPath)
h.SetServerOptions(18800, false, false, nil)
h.SetServerBindHost("192.168.1.10", true)
if got := h.gatewayHostOverride(); got != "" {
t.Fatalf("gatewayHostOverride() = %q, want empty", got)
}
}
func TestGatewayHostExplicitIgnoresPublicFlag(t *testing.T) {
configPath := filepath.Join(t.TempDir(), "config.json")
writeGatewayHostConfig(t, configPath, "127.0.0.1")
h := NewHandler(configPath)
h.SetServerOptions(18800, true, true, nil)
h.SetServerBindHost("127.0.0.1", true)
if got := h.effectiveLauncherPublic(); got {
t.Fatalf("effectiveLauncherPublic() = %t, want false when explicit host is set", got)
}
}
func writeGatewayHostConfig(t *testing.T, configPath, host string) {
t.Helper()
cfg := config.DefaultConfig()
cfg.Gateway.Host = host
if err := config.SaveConfig(configPath, cfg); err != nil {
t.Fatalf("SaveConfig() error = %v", err)
}
}
+25
View File
@@ -2,6 +2,7 @@ package api
import (
"net/http"
"strings"
"sync"
"github.com/sipeed/picoclaw/web/backend/launcherconfig"
@@ -13,6 +14,8 @@ type Handler struct {
serverPort int
serverPublic bool
serverPublicExplicit bool
serverHost string
serverHostExplicit bool
serverCIDRs []string
debug bool
oauthMu sync.Mutex
@@ -29,6 +32,7 @@ func NewHandler(configPath string) *Handler {
return &Handler{
configPath: configPath,
serverPort: launcherconfig.DefaultPort,
serverHost: "127.0.0.1",
oauthFlows: make(map[string]*oauthFlow),
oauthState: make(map[string]string),
weixinFlows: make(map[string]*weixinFlow),
@@ -41,9 +45,30 @@ func (h *Handler) SetServerOptions(port int, public bool, publicExplicit bool, a
h.serverPort = port
h.serverPublic = public
h.serverPublicExplicit = publicExplicit
h.serverHost = "127.0.0.1"
if public {
h.serverHost = "0.0.0.0"
}
h.serverHostExplicit = false
h.serverCIDRs = append([]string(nil), allowedCIDRs...)
}
// SetServerBindHost stores the launcher's effective bind host.
// When explicit is true, the value came from the -host flag.
func (h *Handler) SetServerBindHost(host string, explicit bool) {
host = strings.TrimSpace(host)
if host == "" {
host = "127.0.0.1"
if h.serverPublic {
host = "0.0.0.0"
}
explicit = false
}
h.serverHost = host
h.serverHostExplicit = explicit
}
func (h *Handler) SetDebug(debug bool) {
h.debug = debug
}