Skip to content

Commit 78e1221

Browse files
committed
Remove agent singleton
This causes TLS certificates to be reread on every API request, so if they are refreshed on disk, the extension will pick up the new ones. It also avoids the need to recreating the REST client (which was an ultimately unsuccessful effort to make the extension pick up new certificates).
1 parent d6b798e commit 78e1221

File tree

3 files changed

+11
-50
lines changed

3 files changed

+11
-50
lines changed

CHANGELOG.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,20 @@
22

33
## Unreleased
44

5-
## [v1.4.1](https://github.com/coder/vscode-coder/releases/tag/v1.3.9) (2025-02-19)
5+
- Remove agent singleton so that client TLS certificates are reloaded on every API request.
66

77
### Fixed
88

9+
## [v1.4.1](https://github.com/coder/vscode-coder/releases/tag/v1.4.1) (2025-02-19)
10+
911
- Recreate REST client in spots where confirmStart may have waited indefinitely.
1012

11-
## [v1.4.0](https://github.com/coder/vscode-coder/releases/tag/v1.3.9) (2025-02-04)
13+
## [v1.4.0](https://github.com/coder/vscode-coder/releases/tag/v1.4.0) (2025-02-04)
1214

1315
- Recreate REST client after starting a workspace to ensure fresh TLS certificates.
1416
- Use `coder ssh` subcommand in place of `coder vscodessh`.
1517

16-
## [v1.3.10](https://github.com/coder/vscode-coder/releases/tag/v1.3.9) (2025-01-17)
18+
## [v1.3.10](https://github.com/coder/vscode-coder/releases/tag/v1.3.10) (2025-01-17)
1719

1820
- Fix bug where checking for overridden properties incorrectly converted host name pattern to regular expression.
1921

src/api.ts

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -50,36 +50,6 @@ async function createHttpAgent(): Promise<ProxyAgent> {
5050
})
5151
}
5252

53-
// The agent is a singleton so we only have to listen to the configuration once
54-
// (otherwise we would have to carefully dispose agents to remove their
55-
// configuration listeners), and to share the connection pool.
56-
let agent: Promise<ProxyAgent> | undefined = undefined
57-
58-
/**
59-
* Get the existing agent or create one if necessary. On settings change,
60-
* recreate the agent. The agent on the client is not automatically updated;
61-
* this must be called before every request to get the latest agent.
62-
*/
63-
async function getHttpAgent(): Promise<ProxyAgent> {
64-
if (!agent) {
65-
vscode.workspace.onDidChangeConfiguration((e) => {
66-
if (
67-
// http.proxy and coder.proxyBypass are read each time a request is
68-
// made, so no need to watch them.
69-
e.affectsConfiguration("coder.insecure") ||
70-
e.affectsConfiguration("coder.tlsCertFile") ||
71-
e.affectsConfiguration("coder.tlsKeyFile") ||
72-
e.affectsConfiguration("coder.tlsCaFile") ||
73-
e.affectsConfiguration("coder.tlsAltHost")
74-
) {
75-
agent = createHttpAgent()
76-
}
77-
})
78-
agent = createHttpAgent()
79-
}
80-
return agent
81-
}
82-
8353
/**
8454
* Create an sdk instance using the provided URL and token and hook it up to
8555
* configuration. The token may be undefined if some other form of
@@ -101,7 +71,7 @@ export async function makeCoderSdk(baseUrl: string, token: string | undefined, s
10171
// Configure proxy and TLS.
10272
// Note that by default VS Code overrides the agent. To prevent this, set
10373
// `http.proxySupport` to `on` or `off`.
104-
const agent = await getHttpAgent()
74+
const agent = await createHttpAgent()
10575
config.httpsAgent = agent
10676
config.httpAgent = agent
10777
config.proxy = false

src/remote.ts

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,10 @@ export class Remote {
5151
* Try to get the workspace running. Return undefined if the user canceled.
5252
*/
5353
private async maybeWaitForRunning(
54+
restClient: Api,
5455
workspace: Workspace,
5556
label: string,
5657
binPath: string,
57-
baseUrlRaw: string,
58-
token: string,
5958
): Promise<Workspace | undefined> {
6059
const workspaceName = `${workspace.owner_name}/${workspace.name}`
6160

@@ -95,7 +94,6 @@ export class Remote {
9594
title: "Waiting for workspace build...",
9695
},
9796
async () => {
98-
let restClient = await makeCoderSdk(baseUrlRaw, token, this.storage)
9997
const globalConfigDir = path.dirname(this.storage.getSessionTokenPath(label))
10098
while (workspace.latest_build.status !== "running") {
10199
++attempts
@@ -111,9 +109,6 @@ export class Remote {
111109
if (!(await this.confirmStart(workspaceName))) {
112110
return undefined
113111
}
114-
// Recreate REST client since confirmStart may have waited an
115-
// indeterminate amount of time for confirmation.
116-
restClient = await makeCoderSdk(baseUrlRaw, token, this.storage)
117112
writeEmitter = initWriteEmitterAndTerminal()
118113
this.storage.writeToCoderOutputChannel(`Starting ${workspaceName}...`)
119114
workspace = await startWorkspaceIfStoppedOrFailed(
@@ -131,9 +126,6 @@ export class Remote {
131126
if (!(await this.confirmStart(workspaceName))) {
132127
return undefined
133128
}
134-
// Recreate REST client since confirmStart may have waited an
135-
// indeterminate amount of time for confirmation.
136-
restClient = await makeCoderSdk(baseUrlRaw, token, this.storage)
137129
writeEmitter = initWriteEmitterAndTerminal()
138130
this.storage.writeToCoderOutputChannel(`Starting ${workspaceName}...`)
139131
workspace = await startWorkspaceIfStoppedOrFailed(
@@ -324,16 +316,13 @@ export class Remote {
324316

325317
// If the workspace is not in a running state, try to get it running.
326318
if (workspace.latest_build.status !== "running") {
327-
if (!(await this.maybeWaitForRunning(workspace, parts.label, binaryPath, baseUrlRaw, token))) {
319+
const updatedWorkspace = await this.maybeWaitForRunning(workspaceRestClient, workspace, parts.label, binaryPath)
320+
if (!updatedWorkspace) {
328321
// User declined to start the workspace.
329322
await this.closeRemote()
330-
} else {
331-
// Start over with a fresh REST client because we may have waited an
332-
// indeterminate amount amount of time for confirmation to start the
333-
// workspace.
334-
await this.setup(remoteAuthority)
323+
return
335324
}
336-
return
325+
workspace = updatedWorkspace
337326
}
338327
this.commands.workspace = workspace
339328

0 commit comments

Comments
 (0)