Report public gateway address for remote bridge sessions
This commit is contained in:
parent
19a72e32e9
commit
7f192791b5
@ -1,6 +1,7 @@
|
||||
package acp
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -52,6 +53,7 @@ func handleGatewayConnect(
|
||||
Password: strings.TrimSpace(shared.StringArg(asMap(params["auth"]), "password", "")),
|
||||
},
|
||||
}
|
||||
request.ReportedRemoteAddress = resolveGatewayReportedRemoteAddress(server, request)
|
||||
result := server.gateway.Connect(request, notify)
|
||||
return map[string]any{
|
||||
"ok": result.OK,
|
||||
@ -157,3 +159,55 @@ func parsePositiveInt(value any) int {
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func resolveGatewayReportedRemoteAddress(
|
||||
server *Server,
|
||||
request gatewayruntime.ConnectRequest,
|
||||
) string {
|
||||
if strings.TrimSpace(strings.ToLower(request.Mode)) != "remote" {
|
||||
return ""
|
||||
}
|
||||
if !shouldOverrideGatewayReportedRemoteAddress(request.Endpoint.Host) {
|
||||
return ""
|
||||
}
|
||||
if server != nil {
|
||||
if provider, ok := server.syncedProviderByID("openclaw"); ok {
|
||||
if reported := publicEndpointAddressLabel(provider.Endpoint); reported != "" {
|
||||
return reported
|
||||
}
|
||||
}
|
||||
}
|
||||
return publicEndpointAddressLabel(
|
||||
shared.EnvOrDefault("OPENCLAW_URL", "wss://openclaw.svc.plus"),
|
||||
)
|
||||
}
|
||||
|
||||
func shouldOverrideGatewayReportedRemoteAddress(host string) bool {
|
||||
switch strings.TrimSpace(strings.ToLower(host)) {
|
||||
case "127.0.0.1", "localhost", "::1", "xworkmate-bridge.svc.plus":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func publicEndpointAddressLabel(raw string) string {
|
||||
parsed, err := url.Parse(strings.TrimSpace(raw))
|
||||
if err != nil || strings.TrimSpace(parsed.Hostname()) == "" {
|
||||
return ""
|
||||
}
|
||||
host := strings.TrimSpace(parsed.Hostname())
|
||||
port := strings.TrimSpace(parsed.Port())
|
||||
if port == "" {
|
||||
switch strings.TrimSpace(strings.ToLower(parsed.Scheme)) {
|
||||
case "https", "wss":
|
||||
port = "443"
|
||||
case "http", "ws":
|
||||
port = "80"
|
||||
}
|
||||
}
|
||||
if port == "" {
|
||||
return host
|
||||
}
|
||||
return host + ":" + port
|
||||
}
|
||||
|
||||
54
internal/acp/gateway_runtime_test.go
Normal file
54
internal/acp/gateway_runtime_test.go
Normal file
@ -0,0 +1,54 @@
|
||||
package acp
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"xworkmate-bridge/internal/gatewayruntime"
|
||||
)
|
||||
|
||||
func TestResolveGatewayReportedRemoteAddressUsesSyncedOpenClawEndpoint(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
server := NewServer()
|
||||
server.syncProviders([]syncedProvider{
|
||||
{
|
||||
ProviderID: "openclaw",
|
||||
Label: "OpenClaw",
|
||||
Endpoint: "wss://gateway.example.com",
|
||||
Enabled: true,
|
||||
},
|
||||
})
|
||||
|
||||
got := resolveGatewayReportedRemoteAddress(server, gatewayruntime.ConnectRequest{
|
||||
Mode: "remote",
|
||||
Endpoint: gatewayruntime.Endpoint{
|
||||
Host: "127.0.0.1",
|
||||
Port: 18789,
|
||||
TLS: false,
|
||||
},
|
||||
})
|
||||
|
||||
const want = "gateway.example.com:443"
|
||||
if got != want {
|
||||
t.Fatalf("resolveGatewayReportedRemoteAddress() = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveGatewayReportedRemoteAddressPreservesExplicitPublicRemoteHost(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
server := NewServer()
|
||||
|
||||
got := resolveGatewayReportedRemoteAddress(server, gatewayruntime.ConnectRequest{
|
||||
Mode: "remote",
|
||||
Endpoint: gatewayruntime.Endpoint{
|
||||
Host: "openclaw.svc.plus",
|
||||
Port: 443,
|
||||
TLS: true,
|
||||
},
|
||||
})
|
||||
|
||||
if got != "" {
|
||||
t.Fatalf("expected explicit public remote host to bypass override, got %q", got)
|
||||
}
|
||||
}
|
||||
@ -292,11 +292,7 @@ func (s *session) connect() ConnectResult {
|
||||
s.updateSnapshot(func(snapshot *runtimeSnapshot) {
|
||||
snapshot.Status = "connecting"
|
||||
snapshot.StatusText = "Connecting…"
|
||||
snapshot.RemoteAddress = fmt.Sprintf(
|
||||
"%s:%d",
|
||||
s.config.Endpoint.Host,
|
||||
s.config.Endpoint.Port,
|
||||
)
|
||||
snapshot.RemoteAddress = s.reportedRemoteAddress()
|
||||
snapshot.LastError = ""
|
||||
snapshot.LastErrorCode = ""
|
||||
snapshot.LastErrorDetailCode = ""
|
||||
@ -382,11 +378,7 @@ func (s *session) connectAttempt() (ConnectResult, *GatewayError) {
|
||||
snapshot.Status = "connected"
|
||||
snapshot.StatusText = "Connected"
|
||||
snapshot.ServerName = strings.TrimSpace(stringValue(server["host"]))
|
||||
snapshot.RemoteAddress = fmt.Sprintf(
|
||||
"%s:%d",
|
||||
s.config.Endpoint.Host,
|
||||
s.config.Endpoint.Port,
|
||||
)
|
||||
snapshot.RemoteAddress = s.reportedRemoteAddress()
|
||||
snapshot.MainSessionKey = strings.TrimSpace(
|
||||
stringValue(sessionDefaults["mainSessionKey"]),
|
||||
)
|
||||
@ -421,6 +413,14 @@ func (s *session) connectAttempt() (ConnectResult, *GatewayError) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *session) reportedRemoteAddress() string {
|
||||
reported := strings.TrimSpace(s.config.ReportedRemoteAddress)
|
||||
if reported != "" {
|
||||
return reported
|
||||
}
|
||||
return fmt.Sprintf("%s:%d", s.config.Endpoint.Host, s.config.Endpoint.Port)
|
||||
}
|
||||
|
||||
func (s *session) request(
|
||||
method string,
|
||||
params map[string]any,
|
||||
|
||||
60
internal/gatewayruntime/runtime_reported_address_test.go
Normal file
60
internal/gatewayruntime/runtime_reported_address_test.go
Normal file
@ -0,0 +1,60 @@
|
||||
package gatewayruntime
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestManagerConnectUsesReportedRemoteAddressInSnapshot(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
server := newFakeGatewayServer(t)
|
||||
defer server.Close()
|
||||
|
||||
manager := NewManager()
|
||||
manager.ReconnectDelay = 20 * time.Millisecond
|
||||
|
||||
result := manager.Connect(ConnectRequest{
|
||||
RuntimeID: "runtime-1",
|
||||
Mode: "remote",
|
||||
ClientID: "openclaw-macos",
|
||||
Locale: "en_US",
|
||||
UserAgent: "XWorkmate/1.0.0",
|
||||
Endpoint: Endpoint{
|
||||
Host: "127.0.0.1",
|
||||
Port: server.Port(),
|
||||
TLS: false,
|
||||
},
|
||||
ReportedRemoteAddress: "openclaw.svc.plus:443",
|
||||
ConnectAuthMode: "shared-token",
|
||||
ConnectAuthFields: []string{"token"},
|
||||
ConnectAuthSources: []string{"shared:form"},
|
||||
HasSharedAuth: true,
|
||||
HasDeviceToken: false,
|
||||
PackageInfo: PackageInfo{
|
||||
AppName: "XWorkmate",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
DeviceInfo: DeviceInfo{
|
||||
Platform: "macos",
|
||||
PlatformVersion: "14.0",
|
||||
DeviceFamily: "Mac",
|
||||
ModelIdentifier: "Mac14,5",
|
||||
},
|
||||
Identity: DeviceIdentity{
|
||||
DeviceID: "device-1",
|
||||
PublicKeyBase64URL: "tl4fnKW7VLD0Cl4lQTu2CEgHPs4PWAX7eVgWfWQWk2Q",
|
||||
PrivateKeyBase64URL: "dr7GfMKoO-lJBtgA0dE5m6f_X4kEFsxChDc7mW8mkXu2Xh-cpbsUsPQKXiVBO7YISAc-zg9YBft5WBZ9ZBaTZA",
|
||||
},
|
||||
Auth: AuthConfig{
|
||||
Token: "shared-token",
|
||||
},
|
||||
}, func(map[string]any) {})
|
||||
if !result.OK {
|
||||
t.Fatalf("expected connect success, got %#v", result.Error)
|
||||
}
|
||||
|
||||
if got := result.Snapshot["remoteAddress"]; got != "openclaw.svc.plus:443" {
|
||||
t.Fatalf("expected reported remote address, got %#v", got)
|
||||
}
|
||||
}
|
||||
@ -58,21 +58,22 @@ type AuthConfig struct {
|
||||
}
|
||||
|
||||
type ConnectRequest struct {
|
||||
RuntimeID string
|
||||
Mode string
|
||||
ClientID string
|
||||
Locale string
|
||||
UserAgent string
|
||||
Endpoint Endpoint
|
||||
ConnectAuthMode string
|
||||
ConnectAuthFields []string
|
||||
ConnectAuthSources []string
|
||||
HasSharedAuth bool
|
||||
HasDeviceToken bool
|
||||
PackageInfo PackageInfo
|
||||
DeviceInfo DeviceInfo
|
||||
Identity DeviceIdentity
|
||||
Auth AuthConfig
|
||||
RuntimeID string
|
||||
Mode string
|
||||
ClientID string
|
||||
Locale string
|
||||
UserAgent string
|
||||
Endpoint Endpoint
|
||||
ReportedRemoteAddress string
|
||||
ConnectAuthMode string
|
||||
ConnectAuthFields []string
|
||||
ConnectAuthSources []string
|
||||
HasSharedAuth bool
|
||||
HasDeviceToken bool
|
||||
PackageInfo PackageInfo
|
||||
DeviceInfo DeviceInfo
|
||||
Identity DeviceIdentity
|
||||
Auth AuthConfig
|
||||
}
|
||||
|
||||
type ConnectResult struct {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user