forked from TrueCloudLab/distribution
5b13e95511
This simply moves the registry app to be using the urls package and its exported route names. This supports locking down exported route definitions for use in client packages.
170 lines
3.7 KiB
Go
170 lines
3.7 KiB
Go
package registry
|
|
|
|
import (
|
|
"net/http"
|
|
"net/url"
|
|
|
|
"github.com/docker/docker-registry/api/urls"
|
|
"github.com/docker/docker-registry/digest"
|
|
"github.com/docker/docker-registry/storage"
|
|
"github.com/gorilla/mux"
|
|
)
|
|
|
|
type urlBuilder struct {
|
|
url *url.URL // url root (ie http://localhost/)
|
|
router *mux.Router
|
|
}
|
|
|
|
func newURLBuilder(root *url.URL) *urlBuilder {
|
|
return &urlBuilder{
|
|
url: root,
|
|
router: urls.Router(),
|
|
}
|
|
}
|
|
|
|
func newURLBuilderFromRequest(r *http.Request) *urlBuilder {
|
|
u := &url.URL{
|
|
Scheme: r.URL.Scheme,
|
|
Host: r.Host,
|
|
}
|
|
|
|
return newURLBuilder(u)
|
|
}
|
|
|
|
func newURLBuilderFromString(root string) (*urlBuilder, error) {
|
|
u, err := url.Parse(root)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return newURLBuilder(u), nil
|
|
}
|
|
|
|
func (ub *urlBuilder) buildBaseURL() (string, error) {
|
|
route := clonedRoute(ub.router, urls.RouteNameBase)
|
|
|
|
baseURL, err := route.
|
|
Schemes(ub.url.Scheme).
|
|
Host(ub.url.Host).
|
|
URL()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return baseURL.String(), nil
|
|
}
|
|
|
|
func (ub *urlBuilder) buildTagsURL(name string) (string, error) {
|
|
route := clonedRoute(ub.router, urls.RouteNameTags)
|
|
|
|
tagsURL, err := route.
|
|
Schemes(ub.url.Scheme).
|
|
Host(ub.url.Host).
|
|
URL("name", name)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return tagsURL.String(), nil
|
|
}
|
|
|
|
func (ub *urlBuilder) forManifest(m *storage.Manifest) (string, error) {
|
|
return ub.buildManifestURL(m.Name, m.Tag)
|
|
}
|
|
|
|
func (ub *urlBuilder) buildManifestURL(name, tag string) (string, error) {
|
|
route := clonedRoute(ub.router, urls.RouteNameManifest)
|
|
|
|
manifestURL, err := route.
|
|
Schemes(ub.url.Scheme).
|
|
Host(ub.url.Host).
|
|
URL("name", name, "tag", tag)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return manifestURL.String(), nil
|
|
}
|
|
|
|
func (ub *urlBuilder) forLayer(l storage.Layer) (string, error) {
|
|
return ub.buildLayerURL(l.Name(), l.Digest())
|
|
}
|
|
|
|
func (ub *urlBuilder) buildLayerURL(name string, dgst digest.Digest) (string, error) {
|
|
route := clonedRoute(ub.router, urls.RouteNameBlob)
|
|
|
|
layerURL, err := route.
|
|
Schemes(ub.url.Scheme).
|
|
Host(ub.url.Host).
|
|
URL("name", name, "digest", dgst.String())
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return layerURL.String(), nil
|
|
}
|
|
|
|
func (ub *urlBuilder) buildLayerUploadURL(name string) (string, error) {
|
|
route := clonedRoute(ub.router, urls.RouteNameBlobUpload)
|
|
|
|
uploadURL, err := route.
|
|
Schemes(ub.url.Scheme).
|
|
Host(ub.url.Host).
|
|
URL("name", name)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return uploadURL.String(), nil
|
|
}
|
|
|
|
func (ub *urlBuilder) forLayerUpload(layerUpload storage.LayerUpload) (string, error) {
|
|
return ub.buildLayerUploadResumeURL(layerUpload.Name(), layerUpload.UUID())
|
|
}
|
|
|
|
func (ub *urlBuilder) buildLayerUploadResumeURL(name, uuid string, values ...url.Values) (string, error) {
|
|
route := clonedRoute(ub.router, urls.RouteNameBlobUploadChunk)
|
|
|
|
uploadURL, err := route.
|
|
Schemes(ub.url.Scheme).
|
|
Host(ub.url.Host).
|
|
URL("name", name, "uuid", uuid)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return appendValuesURL(uploadURL, values...).String(), nil
|
|
}
|
|
|
|
// appendValuesURL appends the parameters to the url.
|
|
func appendValuesURL(u *url.URL, values ...url.Values) *url.URL {
|
|
merged := u.Query()
|
|
|
|
for _, v := range values {
|
|
for k, vv := range v {
|
|
merged[k] = append(merged[k], vv...)
|
|
}
|
|
}
|
|
|
|
u.RawQuery = merged.Encode()
|
|
return u
|
|
}
|
|
|
|
// appendValues appends the parameters to the url. Panics if the string is not
|
|
// a url.
|
|
func appendValues(u string, values ...url.Values) string {
|
|
up, err := url.Parse(u)
|
|
|
|
if err != nil {
|
|
panic(err) // should never happen
|
|
}
|
|
|
|
return appendValuesURL(up, values...).String()
|
|
}
|
|
|
|
// clondedRoute returns a clone of the named route from the router.
|
|
func clonedRoute(router *mux.Router, name string) *mux.Route {
|
|
route := new(mux.Route)
|
|
*route = *router.GetRoute(name) // clone the route
|
|
return route
|
|
}
|