added pagination to v2/<name>/tags/list endpoint

Signed-off-by: eyjhb <eyjhbb@gmail.com>
This commit is contained in:
eyjhb 2020-06-30 08:45:56 +02:00
parent febc8733d2
commit 4da2712b52
No known key found for this signature in database
GPG Key ID: 740FAE1502523BD8
2 changed files with 52 additions and 0 deletions

View File

@ -3,6 +3,8 @@ package handlers
import (
"encoding/json"
"net/http"
"sort"
"strconv"
"github.com/distribution/distribution/v3"
"github.com/distribution/distribution/v3/registry/api/errcode"
@ -49,6 +51,51 @@ func (th *tagsHandler) GetTags(w http.ResponseWriter, r *http.Request) {
return
}
// do pagination if requested
q := r.URL.Query()
// get entries after latest, if any specified
if lastEntry := q.Get("last"); lastEntry != "" {
lastEntryIndex := sort.SearchStrings(tags, lastEntry)
// as`sort.SearchStrings` can return len(tags), if the
// specified `lastEntry` is not found, we need to
// ensure it does not panic when slicing.
if lastEntryIndex == len(tags) {
tags = []string{}
} else {
tags = tags[lastEntryIndex+1:]
}
}
// if no error, means that the user requested `n` entries
if n := q.Get("n"); n != "" {
maxEntries, err := strconv.Atoi(n)
if err != nil || maxEntries < 0 {
th.Errors = append(th.Errors, v2.ErrorCodePaginationNumberInvalid.WithDetail(map[string]string{"n": n}))
return
}
// if there is requested more than or
// equal to the amount of tags we have,
// then set the request to equal `len(tags)`.
// the reason for the `=`, is so the else
// clause will only activate if there
// are tags left the user needs.
if maxEntries >= len(tags) {
maxEntries = len(tags)
} else if maxEntries > 0 {
// defined in `catalog.go`
urlStr, err := createLinkEntry(r.URL.String(), maxEntries, tags[maxEntries-1])
if err != nil {
th.Errors = append(th.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
return
}
w.Header().Set("Link", urlStr)
}
tags = tags[:maxEntries]
}
w.Header().Set("Content-Type", "application/json")
enc := json.NewEncoder(w)

View File

@ -3,6 +3,7 @@ package storage
import (
"context"
"path"
"sort"
"github.com/distribution/distribution/v3"
storagedriver "github.com/distribution/distribution/v3/registry/storage/driver"
@ -47,6 +48,10 @@ func (ts *tagStore) All(ctx context.Context) ([]string, error) {
tags = append(tags, filename)
}
// there is no guarantee for the order,
// therefore sort before return.
sort.Strings(tags)
return tags, nil
}