fix(macos): resolve dashboard basePath for local and remote (#15862)
Co-authored-by: 帅小呆1号 <shuaixiaodai1@openclaw.ai>
This commit is contained in:
@@ -619,7 +619,29 @@ actor GatewayEndpointStore {
|
||||
}
|
||||
|
||||
extension GatewayEndpointStore {
|
||||
static func dashboardURL(for config: GatewayConnection.Config) throws -> URL {
|
||||
private static func normalizeDashboardPath(_ rawPath: String?) -> String {
|
||||
let trimmed = (rawPath ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !trimmed.isEmpty else { return "/" }
|
||||
let withLeadingSlash = trimmed.hasPrefix("/") ? trimmed : "/" + trimmed
|
||||
guard withLeadingSlash != "/" else { return "/" }
|
||||
return withLeadingSlash.hasSuffix("/") ? withLeadingSlash : withLeadingSlash + "/"
|
||||
}
|
||||
|
||||
private static func localControlUiBasePath() -> String {
|
||||
let root = OpenClawConfigFile.loadDict()
|
||||
guard let gateway = root["gateway"] as? [String: Any],
|
||||
let controlUi = gateway["controlUi"] as? [String: Any]
|
||||
else {
|
||||
return "/"
|
||||
}
|
||||
return self.normalizeDashboardPath(controlUi["basePath"] as? String)
|
||||
}
|
||||
|
||||
static func dashboardURL(
|
||||
for config: GatewayConnection.Config,
|
||||
mode: AppState.ConnectionMode,
|
||||
localBasePath: String? = nil) throws -> URL
|
||||
{
|
||||
guard var components = URLComponents(url: config.url, resolvingAgainstBaseURL: false) else {
|
||||
throw NSError(domain: "Dashboard", code: 1, userInfo: [
|
||||
NSLocalizedDescriptionKey: "Invalid gateway URL",
|
||||
@@ -633,7 +655,17 @@ extension GatewayEndpointStore {
|
||||
default:
|
||||
components.scheme = "http"
|
||||
}
|
||||
components.path = "/"
|
||||
|
||||
let urlPath = self.normalizeDashboardPath(components.path)
|
||||
if urlPath != "/" {
|
||||
components.path = urlPath
|
||||
} else if mode == .local {
|
||||
let fallbackPath = localBasePath ?? self.localControlUiBasePath()
|
||||
components.path = self.normalizeDashboardPath(fallbackPath)
|
||||
} else {
|
||||
components.path = "/"
|
||||
}
|
||||
|
||||
var queryItems: [URLQueryItem] = []
|
||||
if let token = config.token?.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
!token.isEmpty
|
||||
|
||||
@@ -337,7 +337,7 @@ struct MenuContent: View {
|
||||
private func openDashboard() async {
|
||||
do {
|
||||
let config = try await GatewayEndpointStore.shared.requireConfig()
|
||||
let url = try GatewayEndpointStore.dashboardURL(for: config)
|
||||
let url = try GatewayEndpointStore.dashboardURL(for: config, mode: self.state.connectionMode)
|
||||
NSWorkspace.shared.open(url)
|
||||
} catch {
|
||||
let alert = NSAlert()
|
||||
|
||||
@@ -176,6 +176,48 @@ import Testing
|
||||
#expect(host == "192.168.1.10")
|
||||
}
|
||||
|
||||
@Test func dashboardURLUsesLocalBasePathInLocalMode() throws {
|
||||
let config: GatewayConnection.Config = (
|
||||
url: try #require(URL(string: "ws://127.0.0.1:18789")),
|
||||
token: nil,
|
||||
password: nil
|
||||
)
|
||||
|
||||
let url = try GatewayEndpointStore.dashboardURL(
|
||||
for: config,
|
||||
mode: .local,
|
||||
localBasePath: " control ")
|
||||
#expect(url.absoluteString == "http://127.0.0.1:18789/control/")
|
||||
}
|
||||
|
||||
@Test func dashboardURLSkipsLocalBasePathInRemoteMode() throws {
|
||||
let config: GatewayConnection.Config = (
|
||||
url: try #require(URL(string: "ws://gateway.example:18789")),
|
||||
token: nil,
|
||||
password: nil
|
||||
)
|
||||
|
||||
let url = try GatewayEndpointStore.dashboardURL(
|
||||
for: config,
|
||||
mode: .remote,
|
||||
localBasePath: "/local-ui")
|
||||
#expect(url.absoluteString == "http://gateway.example:18789/")
|
||||
}
|
||||
|
||||
@Test func dashboardURLPrefersPathFromConfigURL() throws {
|
||||
let config: GatewayConnection.Config = (
|
||||
url: try #require(URL(string: "wss://gateway.example:443/remote-ui")),
|
||||
token: nil,
|
||||
password: nil
|
||||
)
|
||||
|
||||
let url = try GatewayEndpointStore.dashboardURL(
|
||||
for: config,
|
||||
mode: .remote,
|
||||
localBasePath: "/local-ui")
|
||||
#expect(url.absoluteString == "https://gateway.example:443/remote-ui/")
|
||||
}
|
||||
|
||||
@Test func normalizeGatewayUrlAddsDefaultPortForWs() {
|
||||
let url = GatewayRemoteConfig.normalizeGatewayUrl("ws://gateway")
|
||||
#expect(url?.port == 18789)
|
||||
|
||||
Reference in New Issue
Block a user