added pagination to v2/<name>/tags/list
endpoint
Signed-off-by: eyjhb <eyjhbb@gmail.com>
This commit is contained in:
parent
febc8733d2
commit
4da2712b52
2 changed files with 52 additions and 0 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue