Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/supervisor/frontend/src/ide/ide-web-socket.ts
2501 views
1
/**
2
* Copyright (c) 2020 Gitpod GmbH. All rights reserved.
3
* Licensed under the GNU Affero General Public License (AGPL).
4
* See License.AGPL.txt in the project root for license information.
5
*/
6
7
import { serverUrl } from "../shared/urls";
8
import { metricsReporter } from "./ide-metrics-service-client";
9
import ReconnectingWebSocket from "reconnecting-websocket";
10
import { Disposable } from "@gitpod/gitpod-protocol/lib/util/disposable";
11
12
let connected = false;
13
const workspaceSockets = new Set<IDEWebSocket>();
14
15
const workspaceOrigin = new URL(window.location.href).origin;
16
const gitpodOrigin = new URL(serverUrl.toString()).origin;
17
const WebSocket = window.WebSocket;
18
function isWorkspaceOrigin(url: string): boolean {
19
const originUrl = new URL(url);
20
originUrl.protocol = window.location.protocol;
21
return originUrl.origin === workspaceOrigin;
22
}
23
function isLocalhostOrigin(url: string): boolean {
24
const originUrl = new URL(url);
25
originUrl.protocol = window.location.protocol;
26
return originUrl.hostname === "localhost";
27
}
28
function isGitpodOrigin(url: string): boolean {
29
const originUrl = new URL(url);
30
originUrl.protocol = window.location.protocol;
31
return originUrl.origin === gitpodOrigin;
32
}
33
/**
34
* IDEWebSocket is a proxy to standard WebSocket
35
* which allows to control when web sockets to the workspace
36
* should be opened or closed.
37
* It should not deviate from standard WebSocket in any other way.
38
*/
39
class IDEWebSocket extends ReconnectingWebSocket {
40
constructor(url: string, protocol?: string | string[]) {
41
super(url, protocol, {
42
WebSocket,
43
startClosed: isWorkspaceOrigin(url) && !connected,
44
maxRetries: 0,
45
connectionTimeout: 2147483647, // disable connection timeout, clients should handle it
46
});
47
let origin = "unknown";
48
if (isWorkspaceOrigin(url)) {
49
origin = "workspace";
50
workspaceSockets.add(this);
51
this.addEventListener("close", () => {
52
workspaceSockets.delete(this);
53
});
54
} else if (isLocalhostOrigin(url)) {
55
origin = "localhost";
56
} else if (isGitpodOrigin(url)) {
57
origin = "gitpod";
58
}
59
metricsReporter.instrumentWebSocket(this as any, origin);
60
}
61
static disconnectWorkspace(): void {
62
for (const socket of workspaceSockets) {
63
socket.close();
64
}
65
}
66
}
67
68
export function install(): void {
69
window.WebSocket = IDEWebSocket as any;
70
}
71
72
export function connectWorkspace(): Disposable {
73
if (connected) {
74
return Disposable.NULL;
75
}
76
connected = true;
77
for (const socket of workspaceSockets) {
78
socket.reconnect();
79
}
80
return Disposable.create(() => disconnectWorkspace());
81
}
82
83
export function disconnectWorkspace(): void {
84
if (!connected) {
85
return;
86
}
87
connected = false;
88
for (const socket of workspaceSockets) {
89
socket.close();
90
}
91
}
92
93