// them to the request headers.
func loadCredential(req *http.Request, url string) bool {
currentPrefix := strings.TrimPrefix(url, "https://")
+ currentPrefix = strings.TrimSuffix(currentPrefix, "/")
+
// Iteratively try prefixes, moving up the path hierarchy.
+ // E.g. example.com/foo/bar, example.com/foo, example.com
for {
headers, ok := credentialCache.Load(currentPrefix)
if !ok {
- currentPrefix, _, ok = strings.Cut(currentPrefix, "/")
- if !ok {
+ lastSlash := strings.LastIndexByte(currentPrefix, '/')
+ if lastSlash == -1 {
return false
}
+ currentPrefix = currentPrefix[:lastSlash]
continue
}
for key, values := range headers.(http.Header) {
func storeCredential(prefix string, header http.Header) {
// Trim "https://" prefix to match the format used in .netrc files.
prefix = strings.TrimPrefix(prefix, "https://")
+ prefix = strings.TrimSuffix(prefix, "/")
if len(header) == 0 {
credentialCache.Delete(prefix)
} else {
t.Errorf("loadCredential:\nhave %q\nwant %q", got.Header, want.Header)
}
}
+
+func TestCredentialCacheTrailingSlash(t *testing.T) {
+ // Store a credential for api.github.com/foo/bar
+ want := http.Request{Header: make(http.Header)}
+ want.SetBasicAuth("user", "pwd")
+ storeCredential("api.github.com/foo", want.Header)
+ got := &http.Request{Header: make(http.Header)}
+ ok := loadCredential(got, "api.github.com/foo/bar")
+ if !ok || !reflect.DeepEqual(got.Header, want.Header) {
+ t.Errorf("parseNetrc:\nhave %q\nwant %q", got.Header, want.Header)
+ }
+ got2 := &http.Request{Header: make(http.Header)}
+ ok = loadCredential(got2, "https://api.github.com/foo/bar/")
+ if !ok || !reflect.DeepEqual(got2.Header, want.Header) {
+ t.Errorf("parseNetrc:\nhave %q\nwant %q", got2.Header, want.Header)
+ }
+}