Skip to content

Commit d27fe7f

Browse files
committed
fix: specify --header-command when running coder start (#526)
1 parent d3f6636 commit d27fe7f

File tree

5 files changed

+39
-23
lines changed

5 files changed

+39
-23
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Fixed
6+
7+
- Use `--header-command` properly when starting a workspace.
8+
59
## [v1.9.1](https://github.com/coder/vscode-coder/releases/tag/v1.9.1) 2025-05-27
610

711
### Fixed

src/api.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import * as vscode from "vscode";
1212
import * as ws from "ws";
1313
import { errToStr } from "./api-helper";
1414
import { CertificateError } from "./error";
15+
import { getHeaderArgs } from "./headers";
1516
import { getProxyForUrl } from "./proxy";
1617
import { Storage } from "./storage";
1718
import { expandPath } from "./util";
@@ -185,6 +186,7 @@ export async function startWorkspaceIfStoppedOrFailed(
185186
const startArgs = [
186187
"--global-config",
187188
globalConfigDir,
189+
...getHeaderArgs(vscode.workspace.getConfiguration()),
188190
"start",
189191
"--yes",
190192
workspace.owner_name + "/" + workspace.name,

src/headers.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import * as cp from "child_process";
2+
import * as os from "os";
23
import * as util from "util";
3-
4-
import { WorkspaceConfiguration } from "vscode";
4+
import type { WorkspaceConfiguration } from "vscode";
5+
import { escapeCommandArg } from "./util";
56

67
export interface Logger {
78
writeToCoderOutputChannel(message: string): void;
@@ -28,6 +29,23 @@ export function getHeaderCommand(
2829
return cmd;
2930
}
3031

32+
export function getHeaderArgs(config: WorkspaceConfiguration): string[] {
33+
// Escape a command line to be executed by the Coder binary, so ssh doesn't substitute variables.
34+
const escapeSubcommand: (str: string) => string =
35+
os.platform() === "win32"
36+
? // On Windows variables are %VAR%, and we need to use double quotes.
37+
(str) => escapeCommandArg(str).replace(/%/g, "%%")
38+
: // On *nix we can use single quotes to escape $VARS.
39+
// Note single quotes cannot be escaped inside single quotes.
40+
(str) => `'${str.replace(/'/g, "'\\''")}'`;
41+
42+
const command = getHeaderCommand(config);
43+
if (!command) {
44+
return [];
45+
}
46+
return ["--header-command", escapeSubcommand(command)];
47+
}
48+
3149
// TODO: getHeaders might make more sense to directly implement on Storage
3250
// but it is difficult to test Storage right now since we use vitest instead of
3351
// the standard extension testing framework which would give us access to vscode

src/remote.ts

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ import { extractAgents } from "./api-helper";
2020
import * as cli from "./cliManager";
2121
import { Commands } from "./commands";
2222
import { featureSetForVersion, FeatureSet } from "./featureSet";
23-
import { getHeaderCommand } from "./headers";
23+
import { getHeaderArgs } from "./headers";
2424
import { Inbox } from "./inbox";
2525
import { SSHConfig, SSHValues, mergeSSHConfigValues } from "./sshConfig";
2626
import { computeSSHProperties, sshSupportsSetEnv } from "./sshSupport";
2727
import { Storage } from "./storage";
2828
import {
2929
AuthorityPrefix,
30+
escapeCommandArg,
3031
expandPath,
3132
findPort,
3233
parseRemoteAuthority,
@@ -758,34 +759,21 @@ export class Remote {
758759
const sshConfig = new SSHConfig(sshConfigFile);
759760
await sshConfig.load();
760761

761-
const escape = (str: string): string => `"${str.replace(/"/g, '\\"')}"`;
762-
// Escape a command line to be executed by the Coder binary, so ssh doesn't substitute variables.
763-
const escapeSubcommand: (str: string) => string =
764-
os.platform() === "win32"
765-
? // On Windows variables are %VAR%, and we need to use double quotes.
766-
(str) => escape(str).replace(/%/g, "%%")
767-
: // On *nix we can use single quotes to escape $VARS.
768-
// Note single quotes cannot be escaped inside single quotes.
769-
(str) => `'${str.replace(/'/g, "'\\''")}'`;
770-
771-
// Add headers from the header command.
772-
let headerArg = "";
773-
const headerCommand = getHeaderCommand(vscode.workspace.getConfiguration());
774-
if (typeof headerCommand === "string" && headerCommand.trim().length > 0) {
775-
headerArg = ` --header-command ${escapeSubcommand(headerCommand)}`;
776-
}
762+
const headerArgs = getHeaderArgs(vscode.workspace.getConfiguration());
763+
const headerArgList =
764+
headerArgs.length > 0 ? ` ${headerArgs.join(" ")}` : "";
777765

778766
const hostPrefix = label
779767
? `${AuthorityPrefix}.${label}--`
780768
: `${AuthorityPrefix}--`;
781769

782770
const proxyCommand = featureSet.wildcardSSH
783-
? `${escape(binaryPath)}${headerArg} --global-config ${escape(
771+
? `${escapeCommandArg(binaryPath)}${headerArgList} --global-config ${escapeCommandArg(
784772
path.dirname(this.storage.getSessionTokenPath(label)),
785-
)} ssh --stdio --usage-app=vscode --disable-autostart --network-info-dir ${escape(this.storage.getNetworkInfoPath())}${await this.formatLogArg(logDir)} --ssh-host-prefix ${hostPrefix} %h`
786-
: `${escape(binaryPath)}${headerArg} vscodessh --network-info-dir ${escape(
773+
)} ssh --stdio --usage-app=vscode --disable-autostart --network-info-dir ${escapeCommandArg(this.storage.getNetworkInfoPath())}${await this.formatLogArg(logDir)} --ssh-host-prefix ${hostPrefix} %h`
774+
: `${escapeCommandArg(binaryPath)}${headerArgList} vscodessh --network-info-dir ${escapeCommandArg(
787775
this.storage.getNetworkInfoPath(),
788-
)}${await this.formatLogArg(logDir)} --session-token-file ${escape(this.storage.getSessionTokenPath(label))} --url-file ${escape(
776+
)}${await this.formatLogArg(logDir)} --session-token-file ${escapeCommandArg(this.storage.getSessionTokenPath(label))} --url-file ${escapeCommandArg(
789777
this.storage.getUrlPath(label),
790778
)} %h`;
791779

src/util.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,7 @@ export function countSubstring(needle: string, haystack: string): number {
143143
}
144144
return count;
145145
}
146+
147+
export function escapeCommandArg(arg: string): string {
148+
return `"${arg.replace(/"/g, '\\"')}"`;
149+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy