Skip to content

Commit

Permalink
refactor(docker): Adding a safer way to retrieve the next link
Browse files Browse the repository at this point in the history
Signed-off-by: Vincent Boutour <[email protected]>
  • Loading branch information
ViBiOh committed May 26, 2021
1 parent 18976cf commit 44c1191
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 7 deletions.
26 changes: 19 additions & 7 deletions pkg/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
const (
registryURL = "https://index.docker.io"
authURL = "https://auth.docker.io/token"
nextLink = `rel="next"`
)

type authResponse struct {
Expand Down Expand Up @@ -108,7 +109,7 @@ func (a app) LatestVersions(repository string, patterns []string) (map[string]se

<-done

url = getNextURL(resp, registry)
url = getNextURL(resp.Header, registry)
}

return versions, nil
Expand All @@ -132,16 +133,27 @@ func (a app) getImageDetails(ctx context.Context, repository string) (string, st
return registryURL, repository, token, nil
}

func getNextURL(resp *http.Response, registry string) string {
link := resp.Header.Get("link")
if len(link) == 0 {
func getNextURL(headers http.Header, registry string) string {
links := headers.Values("link")
if len(links) == 0 {
return ""
}

parts := strings.Split(link, ";")
path := strings.Trim(strings.Trim(parts[0], "<"), ">")
for _, link := range links {
if !strings.Contains(link, nextLink) {
continue
}

for _, part := range strings.Split(link, ";") {
if strings.Contains(part, nextLink) {
continue
}

return fmt.Sprintf("%s%s", registry, strings.TrimSpace(strings.Trim(strings.Trim(part, "<"), ">")))
}
}

return fmt.Sprintf("%s%s", registry, path)
return ""
}

func (a app) login(ctx context.Context, repository string) (string, error) {
Expand Down
59 changes: 59 additions & 0 deletions pkg/docker/docker_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package docker

import (
"net/http"
"testing"
)

func TestGetNextURL(t *testing.T) {
type args struct {
headers http.Header
registry string
}

upperCaseHeader := http.Header{}
upperCaseHeader.Add("Link", `rel="next"; /v2/test`)

lowerCaseHeader := http.Header{}
lowerCaseHeader.Add("link", `rel="prev"; /v2/prev`)
lowerCaseHeader.Add("link", `rel="next"; /v2/next`)

var cases = []struct {
intention string
args args
want string
}{
{
"empty",
args{
headers: http.Header{},
registry: "http://localhost",
},
"",
},
{
"uppercase link with next",
args{
headers: upperCaseHeader,
registry: "http://localhost",
},
"http://localhost/v2/test",
},
{
"lowercase link with previous and next inverted",
args{
headers: lowerCaseHeader,
registry: "http://localhost",
},
"http://localhost/v2/next",
},
}

for _, tc := range cases {
t.Run(tc.intention, func(t *testing.T) {
if got := getNextURL(tc.args.headers, tc.args.registry); got != tc.want {
t.Errorf("getNextURL() =`%s`, want`%s`", got, tc.want)
}
})
}
}

0 comments on commit 44c1191

Please sign in to comment.