1
0
mirror of https://github.com/mayflower/docker-ls.git synced 2025-11-28 00:01:09 +03:00
Files
docker-ls/lib/api_repository_list.go
2016-02-16 09:03:14 +01:00

141 lines
3.0 KiB
Go

package lib
import (
"encoding/json"
"net/http"
"net/url"
"strconv"
)
type RepositoryListResponse struct {
repositories chan *Repository
err error
}
type repositoryListJsonResponse struct {
Repositories *[]string `json:"repositories"`
}
func (r *RepositoryListResponse) Repositories() <-chan *Repository {
return (r.repositories)
}
func (r *RepositoryListResponse) LastError() error {
return r.err
}
func (r *RegistryApi) executeListRequest(url *url.URL, initialRequest bool) (response *http.Response, close bool, err error) {
response, err = r.connector.Get(url)
if err != nil {
return
}
close = response.Close
switch response.StatusCode {
case http.StatusUnauthorized, http.StatusForbidden:
err = genericAuthorizationError
return
case http.StatusNotFound:
if initialRequest {
err = NotImplementedByRemoteError("registry does not implement repository listings")
} else {
err = newInvalidStatusCodeError(response.StatusCode)
}
return
case http.StatusOK:
default:
err = newInvalidStatusCodeError(response.StatusCode)
return
}
return
}
func (r *RegistryApi) iterateRepositoryList(lastApiResponse *http.Response, listResponse *RepositoryListResponse) (apiResponse *http.Response, more bool, err error) {
requestUrl := r.endpointUrl("v2/_catalog")
if lastApiResponse != nil {
linkHeader := lastApiResponse.Header.Get("link")
if linkHeader != "" {
// This is a hack to work around what looks like a bug in the registry:
// the supplied link URL currently lacks scheme and host
scheme, host := requestUrl.Scheme, requestUrl.Host
requestUrl, err = parseLinkToNextHeader(linkHeader)
requestUrl.Scheme = scheme
requestUrl.Host = host
}
if err != nil {
return
}
} else {
queryParams := requestUrl.Query()
queryParams.Set("n", strconv.Itoa(r.pageSize))
requestUrl.RawQuery = queryParams.Encode()
}
apiResponse, needsClose, err := r.executeListRequest(requestUrl, lastApiResponse == nil)
if needsClose {
defer apiResponse.Body.Close()
}
if err != nil {
return
}
more = apiResponse.Header.Get("link") != ""
var jsonResponse repositoryListJsonResponse
decoder := json.NewDecoder(apiResponse.Body)
err = decoder.Decode(&jsonResponse)
if err != nil {
return
}
if jsonResponse.Repositories == nil {
err = genericMalformedResponseError
return
}
for _, repositoryName := range *jsonResponse.Repositories {
listResponse.repositories <- newRepository(repositoryName)
}
return
}
func (r *RegistryApi) ListRepositories() (response *RepositoryListResponse, err error) {
response = &RepositoryListResponse{
repositories: make(chan *Repository, r.pageSize),
}
var apiResponse *http.Response
apiResponse, more, err := r.iterateRepositoryList(apiResponse, response)
go func() {
for more {
var err error
apiResponse, more, err = r.iterateRepositoryList(apiResponse, response)
if err != nil {
response.err = err
break
}
}
close(response.repositories)
}()
return
}