diff --git a/package.json b/package.json index 77a8dda0..6d8c9aaa 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "default": "" }, "coder.headerCommand": { - "markdownDescription": "An external command that outputs additional HTTP headers added to all requests. The command must output each header as `key=value` on its own line. The following environment variables will be available to the process: `CODER_URL`.", + "markdownDescription": "An external command that outputs additional HTTP headers added to all requests. The command must output each header as `key=value` on its own line. The following environment variables will be available to the process: `CODER_URL`. Defaults to the value of `CODER_HEADER_COMMAND` if not set.", "type": "string", "default": "" }, @@ -291,4 +291,4 @@ "trim": "0.0.3", "word-wrap": "1.2.5" } -} +} \ No newline at end of file diff --git a/src/headers.test.ts b/src/headers.test.ts index 422e23ec..1fa5f759 100644 --- a/src/headers.test.ts +++ b/src/headers.test.ts @@ -1,6 +1,7 @@ import * as os from "os" -import { it, expect } from "vitest" -import { getHeaders } from "./headers" +import { it, expect, describe, beforeEach, afterEach, vi } from "vitest" +import { WorkspaceConfiguration } from "vscode" +import { getHeaderCommand, getHeaders } from "./headers" const logger = { writeToCoderOutputChannel() { @@ -55,3 +56,49 @@ it("should have access to environment variables", async () => { it("should error on non-zero exit", async () => { await expect(getHeaders("localhost", "exit 10", logger)).rejects.toMatch(/exited unexpectedly with code 10/) }) + +describe("getHeaderCommand", () => { + beforeEach(() => { + vi.stubEnv("CODER_HEADER_COMMAND", "") + }) + + afterEach(() => { + vi.unstubAllEnvs() + }) + + it("should return undefined if coder.headerCommand is not set in config", () => { + const config = { + get: () => undefined, + } as unknown as WorkspaceConfiguration + + expect(getHeaderCommand(config)).toBeUndefined() + }) + + it("should return undefined if coder.headerCommand is not a string", () => { + const config = { + get: () => 1234, + } as unknown as WorkspaceConfiguration + + expect(getHeaderCommand(config)).toBeUndefined() + }) + + it("should return coder.headerCommand if set in config", () => { + vi.stubEnv("CODER_HEADER_COMMAND", "printf 'x=y'") + + const config = { + get: () => "printf 'foo=bar'", + } as unknown as WorkspaceConfiguration + + expect(getHeaderCommand(config)).toBe("printf 'foo=bar'") + }) + + it("should return CODER_HEADER_COMMAND if coder.headerCommand is not set in config and CODER_HEADER_COMMAND is set in environment", () => { + vi.stubEnv("CODER_HEADER_COMMAND", "printf 'x=y'") + + const config = { + get: () => undefined, + } as unknown as WorkspaceConfiguration + + expect(getHeaderCommand(config)).toBe("printf 'x=y'") + }) +}) diff --git a/src/headers.ts b/src/headers.ts index f9da6168..259ad4a4 100644 --- a/src/headers.ts +++ b/src/headers.ts @@ -1,6 +1,8 @@ import * as cp from "child_process" import * as util from "util" +import { WorkspaceConfiguration } from "vscode" + export interface Logger { writeToCoderOutputChannel(message: string): void } @@ -15,6 +17,14 @@ function isExecException(err: unknown): err is ExecException { return typeof (err as ExecException).code !== "undefined" } +export function getHeaderCommand(config: WorkspaceConfiguration): string | undefined { + const cmd = config.get("coder.headerCommand") || process.env.CODER_HEADER_COMMAND + if (!cmd || typeof cmd !== "string") { + return undefined + } + return cmd +} + // TODO: getHeaders might make more sense to directly implement on Storage // but it is difficult to test Storage right now since we use vitest instead of // the standard extension testing framework which would give us access to vscode diff --git a/src/remote.ts b/src/remote.ts index ae13001f..3e072dd9 100644 --- a/src/remote.ts +++ b/src/remote.ts @@ -20,6 +20,7 @@ import prettyBytes from "pretty-bytes" import * as semver from "semver" import * as vscode from "vscode" import * as ws from "ws" +import { getHeaderCommand } from "./headers" import { SSHConfig, SSHValues, defaultSSHConfigResponse, mergeSSHConfigValues } from "./sshConfig" import { computeSSHProperties, sshSupportsSetEnv } from "./sshSupport" import { Storage } from "./storage" @@ -537,7 +538,7 @@ export class Remote { // Add headers from the header command. let headerArg = "" - const headerCommand = vscode.workspace.getConfiguration().get("coder.headerCommand") + const headerCommand = getHeaderCommand(vscode.workspace.getConfiguration()) if (typeof headerCommand === "string" && headerCommand.trim().length > 0) { headerArg = ` --header-command ${escape(headerCommand)}` } diff --git a/src/storage.ts b/src/storage.ts index 8bd2ceb8..8506464f 100644 --- a/src/storage.ts +++ b/src/storage.ts @@ -11,7 +11,7 @@ import os from "os" import path from "path" import prettyBytes from "pretty-bytes" import * as vscode from "vscode" -import { getHeaders } from "./headers" +import { getHeaderCommand, getHeaders } from "./headers" export class Storage { public workspace?: Workspace @@ -397,7 +397,7 @@ export class Storage { } public async getHeaders(url = this.getURL()): Promise> { - return getHeaders(url, vscode.workspace.getConfiguration().get("coder.headerCommand"), this) + return getHeaders(url, getHeaderCommand(vscode.workspace.getConfiguration()), this) } }