fix(api): skip auth header for unauthenticated source
Summary
glab api regressed for public endpoints when no token is configured, starting in v1.85.0. All glab api calls fail with Unauthenticated. before any request is sent. Other commands are not affected — the manual request path in internal/api/client.go is only used by glab api.
Root cause
Commit 61e07344 (v1.85.0) replaced glab's local UnauthenticatedAuthSource with the go-gitlab client-go gitlab.Unauthenticated{} type. The two behave differently:
- Old:
Header()returned("PRIVATE-TOKEN", "", nil)— no error. - New:
Header()returns("", "", errUnauthenticated)— a sentinel.
The go-gitlab library's AllHeadersAuthStrategy.ApplyAuthHeader recognizes the sentinel via errors.Is(err, errUnauthenticated) and skips setting the header. But glab's NewHTTPRequest (called only by glab api via internal/commands/api/http.go:84) has its own auth path and treats any Header() error as fatal, aborting before the request goes out.
Fix
Mirror the library's behavior locally: skip the header when c.authSource is a gitlab.Unauthenticated. The sentinel error is unexported, so a type check is the cleanest available signal. A comment at the call site points a future reader at the upstream contract.
Follow-up (not in this MR)
glab api is the only command that builds requests via api.NewHTTPRequest instead of routing through the go-gitlab client's request pipeline (release download already uses client.NewRequestToURL + client.Do for the same-host case, and that path handles auth correctly by construction). Refactoring glab api onto that pipeline would delete NewHTTPRequest and the whole class of bug. Worth its own issue.
Test plan
-
go test ./internal/api/... ./internal/commands/api/...passes. -
Regression test
TestNewHTTPRequest_UnauthenticatedAuthSourceadded. -
Manual repro from the issue now succeeds:
GLAB_CONFIG_DIR=/tmp/glab-8383-config GITLAB_TOKEN= ./bin/glab api 'projects/gitlab-org%2Fcli/releases?per_page=1'Returns JSON instead of
Unauthenticated.