diff --git a/registry/client/repository.go b/registry/client/repository.go index ed29cf3f..d8e2c795 100644 --- a/registry/client/repository.go +++ b/registry/client/repository.go @@ -205,13 +205,18 @@ type tags struct { func (t *tags) All(ctx context.Context) ([]string, error) { var tags []string - u, err := t.ub.BuildTagsURL(t.name) + listURLStr, err := t.ub.BuildTagsURL(t.name) + if err != nil { + return tags, err + } + + listURL, err := url.Parse(listURLStr) if err != nil { return tags, err } for { - resp, err := t.client.Get(u) + resp, err := t.client.Get(listURL.String()) if err != nil { return tags, err } @@ -231,7 +236,13 @@ func (t *tags) All(ctx context.Context) ([]string, error) { } tags = append(tags, tagsResponse.Tags...) if link := resp.Header.Get("Link"); link != "" { - u = strings.Trim(strings.Split(link, ";")[0], "<>") + linkURLStr := strings.Trim(strings.Split(link, ";")[0], "<>") + linkURL, err := url.Parse(linkURLStr) + if err != nil { + return tags, err + } + + listURL = listURL.ResolveReference(linkURL) } else { return tags, nil } diff --git a/registry/client/repository_test.go b/registry/client/repository_test.go index 3bcf63e1..4018a928 100644 --- a/registry/client/repository_test.go +++ b/registry/client/repository_test.go @@ -1136,13 +1136,27 @@ func TestManifestTagsPaginated(t *testing.T) { queryParams["n"] = []string{"1"} queryParams["last"] = []string{tagsList[i-1]} } + + // Test both relative and absolute links. + relativeLink := "/v2/" + repo.Name() + "/tags/list?n=1&last=" + tagsList[i] + var link string + switch i { + case 0: + link = relativeLink + case len(tagsList) - 1: + link = "" + default: + link = s.URL + relativeLink + } + headers := http.Header(map[string][]string{ "Content-Length": {fmt.Sprint(len(body))}, "Last-Modified": {time.Now().Add(-1 * time.Second).Format(time.ANSIC)}, }) - if i < 2 { - headers.Set("Link", "<"+s.URL+"/v2/"+repo.Name()+"/tags/list?n=1&last="+tagsList[i]+`>; rel="next"`) + if link != "" { + headers.Set("Link", fmt.Sprintf(`<%s>; rel="next"`, link)) } + m = append(m, testutil.RequestResponseMapping{ Request: testutil.Request{ Method: "GET",