Skip to content

Commit 23e836a

Browse files
fix/config: merge env additional headers over config file headers (#1359)
* fix/config: merge env additional headers over config file headers Previously env-derived additional headers overwrote any additionalHeaders loaded from the config file entirely. Merge them instead, with env headers taking precedence, consistent with how the access token and endpoint are overridden. Config-file keys are normalized to lowercase to match the env-header convention, so env values correctly override differently-cased config keys and the authorization-conflict check catches them. * chore/config: condense additional-headers merge comment
1 parent cadb64a commit 23e836a

2 files changed

Lines changed: 67 additions & 1 deletion

File tree

cmd/src/main.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,16 @@ func readConfig() (*config, error) {
337337
}
338338
}
339339

340-
cfg.additionalHeaders = parseAdditionalHeaders()
340+
// Merge config-file headers under the env headers (which take precedence),
341+
// lowercasing config keys to match the env-header convention.
342+
envHeaders := parseAdditionalHeaders()
343+
for k, v := range cfg.additionalHeaders {
344+
lk := strings.ToLower(k)
345+
if _, ok := envHeaders[lk]; !ok {
346+
envHeaders[lk] = v
347+
}
348+
}
349+
cfg.additionalHeaders = envHeaders
341350
// Ensure that we're not clashing additonal headers
342351
_, hasAuthorizationAdditonalHeader := cfg.additionalHeaders["authorization"]
343352
if cfg.accessToken != "" && hasAuthorizationAdditonalHeader {

cmd/src/main_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,63 @@ func TestReadConfig(t *testing.T) {
358358
inCI: true,
359359
},
360360
},
361+
{
362+
name: "config file additional headers preserved when endpoint/token from environment",
363+
fileContents: &configFromFile{
364+
Endpoint: "https://example.com/",
365+
AccessToken: "deadbeef",
366+
AdditionalHeaders: map[string]string{"x-proxy-token": "secret"},
367+
},
368+
envToken: "abc",
369+
envEndpoint: "https://override.com",
370+
want: &config{
371+
endpointURL: &url.URL{Scheme: "https", Host: "override.com"},
372+
accessToken: "abc",
373+
additionalHeaders: map[string]string{"x-proxy-token": "secret"},
374+
},
375+
},
376+
{
377+
name: "config file additional headers merged with environment headers",
378+
fileContents: &configFromFile{
379+
Endpoint: "https://example.com/",
380+
AccessToken: "deadbeef",
381+
AdditionalHeaders: map[string]string{"x-proxy-token": "secret"},
382+
},
383+
envFooHeader: "bar",
384+
want: &config{
385+
endpointURL: &url.URL{Scheme: "https", Host: "example.com"},
386+
accessToken: "deadbeef",
387+
additionalHeaders: map[string]string{"x-proxy-token": "secret", "foo": "bar"},
388+
},
389+
},
390+
{
391+
name: "environment headers override config file headers",
392+
fileContents: &configFromFile{
393+
Endpoint: "https://example.com/",
394+
AccessToken: "deadbeef",
395+
AdditionalHeaders: map[string]string{"foo": "from-config"},
396+
},
397+
envFooHeader: "from-env",
398+
want: &config{
399+
endpointURL: &url.URL{Scheme: "https", Host: "example.com"},
400+
accessToken: "deadbeef",
401+
additionalHeaders: map[string]string{"foo": "from-env"},
402+
},
403+
},
404+
{
405+
name: "environment headers override differently-cased config file headers",
406+
fileContents: &configFromFile{
407+
Endpoint: "https://example.com/",
408+
AccessToken: "deadbeef",
409+
AdditionalHeaders: map[string]string{"Foo": "from-config"},
410+
},
411+
envFooHeader: "from-env",
412+
want: &config{
413+
endpointURL: &url.URL{Scheme: "https", Host: "example.com"},
414+
accessToken: "deadbeef",
415+
additionalHeaders: map[string]string{"foo": "from-env"},
416+
},
417+
},
361418
}
362419

363420
for _, test := range tests {

0 commit comments

Comments
 (0)