refactor: centralize dashboard url + ws close code
This commit is contained in:
@@ -388,6 +388,43 @@ actor GatewayEndpointStore {
|
||||
}
|
||||
}
|
||||
|
||||
extension GatewayEndpointStore {
|
||||
static func dashboardURL(for config: GatewayConnection.Config) throws -> URL {
|
||||
guard var components = URLComponents(url: config.url, resolvingAgainstBaseURL: false) else {
|
||||
throw NSError(domain: "Dashboard", code: 1, userInfo: [
|
||||
NSLocalizedDescriptionKey: "Invalid gateway URL",
|
||||
])
|
||||
}
|
||||
switch components.scheme?.lowercased() {
|
||||
case "ws":
|
||||
components.scheme = "http"
|
||||
case "wss":
|
||||
components.scheme = "https"
|
||||
default:
|
||||
components.scheme = "http"
|
||||
}
|
||||
components.path = "/"
|
||||
var queryItems: [URLQueryItem] = []
|
||||
if let token = config.token?.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
!token.isEmpty
|
||||
{
|
||||
queryItems.append(URLQueryItem(name: "token", value: token))
|
||||
}
|
||||
if let password = config.password?.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
!password.isEmpty
|
||||
{
|
||||
queryItems.append(URLQueryItem(name: "password", value: password))
|
||||
}
|
||||
components.queryItems = queryItems.isEmpty ? nil : queryItems
|
||||
guard let url = components.url else {
|
||||
throw NSError(domain: "Dashboard", code: 2, userInfo: [
|
||||
NSLocalizedDescriptionKey: "Failed to build dashboard URL",
|
||||
])
|
||||
}
|
||||
return url
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
extension GatewayEndpointStore {
|
||||
static func _testResolveGatewayPassword(
|
||||
|
||||
@@ -313,34 +313,7 @@ struct MenuContent: View {
|
||||
private func openDashboard() async {
|
||||
do {
|
||||
let config = try await GatewayEndpointStore.shared.requireConfig()
|
||||
let wsURL = config.url
|
||||
guard var components = URLComponents(url: wsURL, resolvingAgainstBaseURL: false) else {
|
||||
throw NSError(domain: "Dashboard", code: 1, userInfo: [
|
||||
NSLocalizedDescriptionKey: "Invalid gateway URL",
|
||||
])
|
||||
}
|
||||
switch components.scheme?.lowercased() {
|
||||
case "ws":
|
||||
components.scheme = "http"
|
||||
case "wss":
|
||||
components.scheme = "https"
|
||||
default:
|
||||
components.scheme = "http"
|
||||
}
|
||||
components.path = "/"
|
||||
var queryItems: [URLQueryItem] = []
|
||||
if let token = config.token, !token.isEmpty {
|
||||
queryItems.append(URLQueryItem(name: "token", value: token))
|
||||
}
|
||||
if let password = config.password, !password.isEmpty {
|
||||
queryItems.append(URLQueryItem(name: "password", value: password))
|
||||
}
|
||||
components.queryItems = queryItems.isEmpty ? nil : queryItems
|
||||
guard let url = components.url else {
|
||||
throw NSError(domain: "Dashboard", code: 2, userInfo: [
|
||||
NSLocalizedDescriptionKey: "Failed to build dashboard URL",
|
||||
])
|
||||
}
|
||||
let url = try GatewayEndpointStore.dashboardURL(for: config)
|
||||
NSWorkspace.shared.open(url)
|
||||
} catch {
|
||||
let alert = NSAlert()
|
||||
|
||||
@@ -50,6 +50,9 @@ export type GatewayBrowserClientOptions = {
|
||||
onGap?: (info: { expected: number; received: number }) => void;
|
||||
};
|
||||
|
||||
// 4008 = application-defined code (browser rejects 1008 "Policy Violation")
|
||||
const CONNECT_FAILED_CLOSE_CODE = 4008;
|
||||
|
||||
export class GatewayBrowserClient {
|
||||
private ws: WebSocket | null = null;
|
||||
private pending = new Map<string, Pending>();
|
||||
@@ -134,8 +137,7 @@ export class GatewayBrowserClient {
|
||||
this.opts.onHello?.(hello);
|
||||
})
|
||||
.catch(() => {
|
||||
// 4008 = application-defined code (browser rejects 1008 "Policy Violation")
|
||||
this.ws?.close(4008, "connect failed");
|
||||
this.ws?.close(CONNECT_FAILED_CLOSE_CODE, "connect failed");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user