diff --git a/cmd/src/main.go b/cmd/src/main.go index fd217ba51f..7bb75e6211 100644 --- a/cmd/src/main.go +++ b/cmd/src/main.go @@ -337,7 +337,16 @@ func readConfig() (*config, error) { } } - cfg.additionalHeaders = parseAdditionalHeaders() + // Merge config-file headers under the env headers (which take precedence), + // lowercasing config keys to match the env-header convention. + envHeaders := parseAdditionalHeaders() + for k, v := range cfg.additionalHeaders { + lk := strings.ToLower(k) + if _, ok := envHeaders[lk]; !ok { + envHeaders[lk] = v + } + } + cfg.additionalHeaders = envHeaders // Ensure that we're not clashing additonal headers _, hasAuthorizationAdditonalHeader := cfg.additionalHeaders["authorization"] if cfg.accessToken != "" && hasAuthorizationAdditonalHeader { diff --git a/cmd/src/main_test.go b/cmd/src/main_test.go index 0b23cb9938..277285b1db 100644 --- a/cmd/src/main_test.go +++ b/cmd/src/main_test.go @@ -358,6 +358,63 @@ func TestReadConfig(t *testing.T) { inCI: true, }, }, + { + name: "config file additional headers preserved when endpoint/token from environment", + fileContents: &configFromFile{ + Endpoint: "https://example.com/", + AccessToken: "deadbeef", + AdditionalHeaders: map[string]string{"x-proxy-token": "secret"}, + }, + envToken: "abc", + envEndpoint: "https://override.com", + want: &config{ + endpointURL: &url.URL{Scheme: "https", Host: "override.com"}, + accessToken: "abc", + additionalHeaders: map[string]string{"x-proxy-token": "secret"}, + }, + }, + { + name: "config file additional headers merged with environment headers", + fileContents: &configFromFile{ + Endpoint: "https://example.com/", + AccessToken: "deadbeef", + AdditionalHeaders: map[string]string{"x-proxy-token": "secret"}, + }, + envFooHeader: "bar", + want: &config{ + endpointURL: &url.URL{Scheme: "https", Host: "example.com"}, + accessToken: "deadbeef", + additionalHeaders: map[string]string{"x-proxy-token": "secret", "foo": "bar"}, + }, + }, + { + name: "environment headers override config file headers", + fileContents: &configFromFile{ + Endpoint: "https://example.com/", + AccessToken: "deadbeef", + AdditionalHeaders: map[string]string{"foo": "from-config"}, + }, + envFooHeader: "from-env", + want: &config{ + endpointURL: &url.URL{Scheme: "https", Host: "example.com"}, + accessToken: "deadbeef", + additionalHeaders: map[string]string{"foo": "from-env"}, + }, + }, + { + name: "environment headers override differently-cased config file headers", + fileContents: &configFromFile{ + Endpoint: "https://example.com/", + AccessToken: "deadbeef", + AdditionalHeaders: map[string]string{"Foo": "from-config"}, + }, + envFooHeader: "from-env", + want: &config{ + endpointURL: &url.URL{Scheme: "https", Host: "example.com"}, + accessToken: "deadbeef", + additionalHeaders: map[string]string{"foo": "from-env"}, + }, + }, } for _, test := range tests {