Skip to content

Commit 2d79605

Browse files
committed
Add file shutdown action and endpoint with allow-shutdown
1 parent 6448408 commit 2d79605

File tree

4 files changed

+129
-0
lines changed

4 files changed

+129
-0
lines changed

patches/series

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ getting-started.diff
2020
keepalive.diff
2121
clipboard.diff
2222
display-language.diff
23+
shutdown.diff

patches/shutdown.diff

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
Add a File > Exit menu item and a command to shutdown the server.
2+
3+
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
4+
===================================================================
5+
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
6+
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
7+
@@ -316,7 +316,8 @@ export class WebClientServer {
8+
codeServerVersion: this._productService.codeServerVersion,
9+
rootEndpoint: base,
10+
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
11+
- logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
12+
+ logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" && this._environmentService.args['auth'] !== "http-basic" ? base + '/logout' : undefined,
13+
+ shutdownEndpoint: this._environmentService.args['allow-shutdown'] ? base + '/shutdown' : undefined,
14+
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
15+
serviceWorker: {
16+
scope: vscodeBase + '/',
17+
Index: code-server/lib/vscode/src/vs/base/common/product.ts
18+
===================================================================
19+
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
20+
+++ code-server/lib/vscode/src/vs/base/common/product.ts
21+
@@ -59,6 +59,7 @@ export interface IProductConfiguration {
22+
readonly rootEndpoint?: string
23+
readonly updateEndpoint?: string
24+
readonly logoutEndpoint?: string
25+
+ readonly shutdownEndpoint?: string
26+
readonly proxyEndpointTemplate?: string
27+
readonly serviceWorker?: {
28+
readonly path: string;
29+
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
30+
===================================================================
31+
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
32+
+++ code-server/lib/vscode/src/vs/workbench/browser/client.ts
33+
@@ -9,6 +9,7 @@ import { IStorageService, StorageScope,
34+
35+
export class CodeServerClient extends Disposable {
36+
static LOGOUT_COMMAND_ID = 'code-server.logout';
37+
+ static SHUTDOWN_COMMAND_ID = 'code-server.shutdown';
38+
39+
constructor (
40+
@ILogService private logService: ILogService,
41+
@@ -90,6 +91,10 @@ export class CodeServerClient extends Di
42+
this.addLogoutCommand(this.productService.logoutEndpoint);
43+
}
44+
45+
+ if (this.productService.shutdownEndpoint) {
46+
+ this.addShutdownCommand(this.productService.shutdownEndpoint);
47+
+ }
48+
+
49+
if (this.productService.serviceWorker) {
50+
await this.registerServiceWorker(this.productService.serviceWorker);
51+
}
52+
@@ -164,6 +169,22 @@ export class CodeServerClient extends Di
53+
},
54+
});
55+
}
56+
+ }
57+
+
58+
+ private addShutdownCommand(shutdownEndpoint: string) {
59+
+ CommandsRegistry.registerCommand(CodeServerClient.SHUTDOWN_COMMAND_ID, () => {
60+
+ const shutdownUrl = new URL(shutdownEndpoint, window.location.href);
61+
+ window.location.assign(shutdownUrl);
62+
+ });
63+
+
64+
+ for (const menuId of [MenuId.CommandPalette, MenuId.MenubarHomeMenu]) {
65+
+ MenuRegistry.appendMenuItem(menuId, {
66+
+ command: {
67+
+ id: CodeServerClient.SHUTDOWN_COMMAND_ID,
68+
+ title: localize('exit', "Exit"),
69+
+ },
70+
+ });
71+
+ }
72+
}
73+
74+
private async registerServiceWorker(serviceWorker: { path: string; scope: string }) {
75+
Index: code-server/src/node/routes/index.ts
76+
===================================================================
77+
--- code-server.orig/src/node/routes/index.ts
78+
+++ code-server/src/node/routes/index.ts
79+
@@ -170,6 +170,15 @@ export const register = async (app: App,
80+
app.router.all("/logout", (req, res) => redirect(req, res, "/", {}))
81+
}
82+
83+
+ if (args["allow-shutdown"] ) {
84+
+ app.router.use("/shutdown", async (req, res) => {
85+
+ res.send("Shutting down...")
86+
+ process.exit(0)
87+
+ })
88+
+ } else {
89+
+ app.router.use("/shutdown", (req, res) => redirect(req, res, "/", {}))
90+
+ }
91+
+
92+
app.router.use("/update", update.router)
93+
94+
// Note that the root route is replaced in Coder Enterprise by the plugin API.
95+
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
96+
===================================================================
97+
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
98+
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
99+
@@ -16,6 +16,8 @@ export const serverOptions: OptionDescri
100+
/* ----- code-server ----- */
101+
'disable-update-check': { type: 'boolean' },
102+
'auth': { type: 'string' },
103+
+ 'allow-shutdown': { type: 'boolean' },
104+
'disable-file-downloads': { type: 'boolean' },
105+
'disable-file-uploads': { type: 'boolean' },
106+
'disable-getting-started-override': { type: 'boolean' },
107+
@@ -103,6 +105,8 @@ export interface ServerParsedArgs {
108+
/* ----- code-server ----- */
109+
'disable-update-check'?: boolean;
110+
'auth'?: string;
111+
+ 'allow-shutdown'?: boolean;
112+
'disable-file-downloads'?: boolean;
113+
'disable-file-uploads'?: boolean;
114+
'disable-getting-started-override'?: boolean,

src/node/cli.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export class OptionalString extends Optional<string> {}
3535
*/
3636
export interface UserProvidedCodeArgs {
3737
"disable-telemetry"?: boolean
38+
"allow-shutdown"?: boolean
3839
force?: boolean
3940
"user-data-dir"?: string
4041
"enable-proposed-api"?: string[]
@@ -164,6 +165,10 @@ export const options: Options<Required<UserProvidedArgs>> = {
164165
},
165166
"cert-key": { type: "string", path: true, description: "Path to certificate key when using non-generated cert." },
166167
"disable-telemetry": { type: "boolean", description: "Disable telemetry." },
168+
"allow-shutdown": {
169+
type: "boolean",
170+
description: "Allow the server to be shut down remotely.",
171+
},
167172
"disable-update-check": {
168173
type: "boolean",
169174
description:

src/node/routes/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,15 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
170170
app.router.all("/logout", (req, res) => redirect(req, res, "/", {}))
171171
}
172172

173+
if (args["allow-shutdown"] ) {
174+
app.router.use("/shutdown", async (req, res) => {
175+
res.send("Shutting down...")
176+
process.exit(0)
177+
})
178+
} else {
179+
app.router.use("/shutdown", (req, res) => redirect(req, res, "/", {}))
180+
}
181+
173182
app.router.use("/update", update.router)
174183

175184
// Note that the root route is replaced in Coder Enterprise by the plugin API.

0 commit comments

Comments
 (0)