diff --git a/CHANGELOG.md b/CHANGELOG.md index b20fcc7..104c217 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - support for configuring the SSH config path, letting Toolbox manage a separate SSH config file instead of always writing to `~/.ssh/config` +- the header command falls back to the `CODER_HEADER_COMMAND` environment variable when the setting is blank, matching the Coder CLI and the VS Code extension ## 0.9.3 - 2026-08-11 diff --git a/README.md b/README.md index 10c5b0c..4d04d01 100644 --- a/README.md +++ b/README.md @@ -509,7 +509,7 @@ explicit entry per resolved workspace/agent using expansion. - `Header command` command that outputs additional HTTP headers. Each line of output must be in the format key=value. - The environment variable CODER_URL will be available to the command process. + When this setting is left blank, the `CODER_HEADER_COMMAND` environment variable is used instead, if set. - `lastDeploymentURL` the last Coder deployment URL that Coder Toolbox successfully authenticated to. diff --git a/src/main/kotlin/com/coder/toolbox/settings/ReadOnlyCoderSettings.kt b/src/main/kotlin/com/coder/toolbox/settings/ReadOnlyCoderSettings.kt index 04576d5..80f799f 100644 --- a/src/main/kotlin/com/coder/toolbox/settings/ReadOnlyCoderSettings.kt +++ b/src/main/kotlin/com/coder/toolbox/settings/ReadOnlyCoderSettings.kt @@ -93,8 +93,8 @@ interface ReadOnlyCoderSettings { /** * 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. + * line. When this setting is blank, the CODER_HEADER_COMMAND environment + * variable (the same variable the Coder CLI reads) is used instead, if set. */ val headerCommand: String? diff --git a/src/main/kotlin/com/coder/toolbox/store/CoderSettingsStore.kt b/src/main/kotlin/com/coder/toolbox/store/CoderSettingsStore.kt index 22abc0e..e91a02b 100644 --- a/src/main/kotlin/com/coder/toolbox/store/CoderSettingsStore.kt +++ b/src/main/kotlin/com/coder/toolbox/store/CoderSettingsStore.kt @@ -54,7 +54,9 @@ class CoderSettingsStore( override val globalDataDirectory: String get() = getDefaultGlobalDataDir().normalize().toString() override val globalConfigDir: String get() = getDefaultGlobalConfigDir().normalize().toString() override val enableDownloads: Boolean get() = store[ENABLE_DOWNLOADS]?.toBooleanStrictOrNull() ?: true - override val headerCommand: String? get() = store[HEADER_COMMAND] + override val headerCommand: String? + get() = store[HEADER_COMMAND].takeUnless { it.isNullOrEmpty() } + ?: env.get(CODER_HEADER_COMMAND).takeUnless { it.isEmpty() } override val tls: ReadOnlyTLSSettings get() = TLSSettings( certPath = store[TLS_CERT_PATH], diff --git a/src/main/kotlin/com/coder/toolbox/store/StoreKeys.kt b/src/main/kotlin/com/coder/toolbox/store/StoreKeys.kt index 69fea40..2a95b34 100644 --- a/src/main/kotlin/com/coder/toolbox/store/StoreKeys.kt +++ b/src/main/kotlin/com/coder/toolbox/store/StoreKeys.kt @@ -2,6 +2,8 @@ package com.coder.toolbox.store internal const val CODER_SSH_CONFIG_OPTIONS = "CODER_SSH_CONFIG_OPTIONS" +internal const val CODER_HEADER_COMMAND = "CODER_HEADER_COMMAND" + internal const val LAST_USED_URL = "lastDeploymentURL" internal const val DEFAULT_URL = "defaultURL" diff --git a/src/test/kotlin/com/coder/toolbox/settings/CoderSettingsTest.kt b/src/test/kotlin/com/coder/toolbox/settings/CoderSettingsTest.kt index 6905683..c78473d 100644 --- a/src/test/kotlin/com/coder/toolbox/settings/CoderSettingsTest.kt +++ b/src/test/kotlin/com/coder/toolbox/settings/CoderSettingsTest.kt @@ -1,5 +1,6 @@ package com.coder.toolbox.settings +import com.coder.toolbox.store.CODER_HEADER_COMMAND import com.coder.toolbox.store.CODER_SSH_CONFIG_OPTIONS import com.coder.toolbox.store.CoderSettingsStore import com.coder.toolbox.store.DISABLE_AUTOSTART @@ -236,6 +237,30 @@ internal class CoderSettingsTest { assertEquals(Pair("http://test.toolbox.coder.com$expected", null), got) } + @Test + fun testHeaderCommand() { + var settings = CoderSettingsStore( + pluginTestSettingsStore(HEADER_COMMAND to "header command from state"), + Environment(), logger + ) + assertEquals("header command from state", settings.readOnly().headerCommand) + + settings = CoderSettingsStore( + pluginTestSettingsStore(), + env = Environment(mapOf(CODER_HEADER_COMMAND to "header command from env")), + logger + ) + assertEquals("header command from env", settings.readOnly().headerCommand) + + // State has precedence. + settings = CoderSettingsStore( + pluginTestSettingsStore(HEADER_COMMAND to "header command from state"), + env = Environment(mapOf(CODER_HEADER_COMMAND to "header command from env")), + logger + ) + assertEquals("header command from state", settings.readOnly().headerCommand) + } + @Test fun testSSHConfigOptions() { var settings = CoderSettingsStore(