Skip to content

config: fix file-backed http_headers path rebasing#912

Open
immanuwell wants to merge 2 commits into
prometheus:mainfrom
immanuwell:fix-http-headers-setdirectory
Open

config: fix file-backed http_headers path rebasing#912
immanuwell wants to merge 2 commits into
prometheus:mainfrom
immanuwell:fix-http-headers-setdirectory

Conversation

@immanuwell

Copy link
Copy Markdown

@roidelapluie @gotjosh small fix here, easy miss.

Headers.SetDirectory mutates Header values from a map copy, so paths from http_headers.files never get written back.
That makes file-backed headers fail when the HTTP config is loaded from a nested path, kind of a footgun.

This just writes the updated header back into the map and adds coverage for the helper and the real LoadHTTPConfigFile plus NewClientFromConfig path.

Repro on main:

  1. Put an HTTP config in configs/http.yml.
  2. Set http_headers to files: [configs/header-value].
  3. Load it with LoadHTTPConfigFile, build a client, send a request.
  4. The request fails with unable to read headers file.

With this patch it reads the file and sends the header.

Signed-off-by: immanuwell <pchpr.00@list.ru>
@immanuwell immanuwell force-pushed the fix-http-headers-setdirectory branch from 89bb161 to 3c24acf Compare June 1, 2026 07:14
@roidelapluie

Copy link
Copy Markdown
Member

can you resolve conflicts?

@immanuwell

Copy link
Copy Markdown
Author

@roidelapluie done, conflicts are resolved

@roidelapluie

Copy link
Copy Markdown
Member

Thanks for the patch and the detailed repro! I dug into this and I don't think the change in headers.go is actually fixing a bug.

Header.Files is a slice, and Header.SetDirectory mutates the slice elements in place (h.Files[i] = JoinDir(...)). When range copies the Header struct, the copy shares the same backing array, so the in-place writes are already visible through the map value. The original loop rebases the paths correctly — the explicit write-back is a no-op for correctness.

I verified this empirically: the integration test in this PR passes against unmodified main (without the headers.go change), with the file path correctly rebased.

On the tests: the file-backed-header path through LoadHTTPConfigFileNewClientFromConfig → real request is already covered by TestHeaders (testdata/http.conf.headers.good.yaml uses files: [testdata/headers-file]) and TestMultipleHeaders. So TestHeadersFileRelativeToConfigFile is redundant and we don't need it.

That said, while looking into this I think the real footgun is elsewhere: LoadHTTPConfigFile calls cfg.SetDirectory(filepath.Dir(filepath.Dir(filename))) — a double filepath.Dir. That resolves relative file paths against the config file's grandparent directory instead of its own directory, which is inconsistent with the SetDirectory contract and every other config loader. It's masked in the fixtures because they prefix paths with the config dir name (e.g. testdata/... for configs that already live in testdata/). That's worth fixing separately, with fixture updates and a changelog note since it's public-API behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants