in proxy/registryoverride/server.go [63:140]
func (s *Server) catalogHandler(w http.ResponseWriter, r *http.Request) error {
limitQ := "n"
offsetQ := "last"
// Build request for ListWithPagination.
var filter tagclient.ListFilter
u := r.URL
q := u.Query()
for k, v := range q {
if len(v) != 1 {
return handler.Errorf(
"invalid query %s:%s", k, v).Status(http.StatusBadRequest)
}
switch k {
case limitQ:
limitCount, err := strconv.Atoi(v[0])
if err != nil {
return handler.Errorf(
"invalid limit %s: %s", v, err).Status(http.StatusBadRequest)
}
if limitCount == 0 {
return handler.Errorf(
"invalid limit %d", limitCount).Status(http.StatusBadRequest)
}
filter.Limit = limitCount
case offsetQ:
filter.Offset = v[0]
default:
return handler.Errorf("invalid query %s", k).Status(http.StatusBadRequest)
}
}
// List with pagination.
listResp, err := s.tagClient.ListWithPagination("", filter)
if err != nil {
return handler.Errorf("list: %s", err)
}
repos := stringset.New()
for _, tag := range listResp.Result {
parts := strings.Split(tag, ":")
if len(parts) != 2 {
log.With("tag", tag).Errorf("Invalid tag format, expected repo:tag")
continue
}
repos.Add(parts[0])
}
// Build Link for response.
offset, err := listResp.GetOffset()
if err != nil && err != io.EOF {
return handler.Errorf("invalid offset %s", err)
}
if offset != "" {
nextUrl, err := url.Parse(u.String())
if err != nil {
return handler.Errorf(
"invalid url string: %s", err).Status(http.StatusBadRequest)
}
val, err := url.ParseQuery(nextUrl.RawQuery)
if err != nil {
return handler.Errorf(
"invalid url string: %s", err).Status(http.StatusBadRequest)
}
val.Set(offsetQ, offset)
nextUrl.RawQuery = val.Encode()
// Set header (https://docs.docker.com/registry/spec/api/#pagination),
// except the host and scheme.
// Link: <<url>?n=2&last=b>; rel="next"
w.Header().Set("Link", fmt.Sprintf("%s; rel=\"next\"", nextUrl.String()))
}
resp := catalogResponse{Repositories: repos.ToSlice()}
if err := json.NewEncoder(w).Encode(&resp); err != nil {
return handler.Errorf("json encode: %s", err)
}
return nil
}