mirror of
https://github.com/rancher/os.git
synced 2025-09-03 07:44:21 +00:00
Bump libcompose and its dependencies
This commit is contained in:
10
vendor/github.com/docker/distribution/registry/api/v2/descriptors.go
generated
vendored
10
vendor/github.com/docker/distribution/registry/api/v2/descriptors.go
generated
vendored
@@ -271,7 +271,7 @@ type MethodDescriptor struct {
|
||||
// RequestDescriptor per API use case.
|
||||
type RequestDescriptor struct {
|
||||
// Name provides a short identifier for the request, usable as a title or
|
||||
// to provide quick context for the particalar request.
|
||||
// to provide quick context for the particular request.
|
||||
Name string
|
||||
|
||||
// Description should cover the requests purpose, covering any details for
|
||||
@@ -303,14 +303,14 @@ type RequestDescriptor struct {
|
||||
// ResponseDescriptor describes the components of an API response.
|
||||
type ResponseDescriptor struct {
|
||||
// Name provides a short identifier for the response, usable as a title or
|
||||
// to provide quick context for the particalar response.
|
||||
// to provide quick context for the particular response.
|
||||
Name string
|
||||
|
||||
// Description should provide a brief overview of the role of the
|
||||
// response.
|
||||
Description string
|
||||
|
||||
// StatusCode specifies the status recieved by this particular response.
|
||||
// StatusCode specifies the status received by this particular response.
|
||||
StatusCode int
|
||||
|
||||
// Headers covers any headers that may be returned from the response.
|
||||
@@ -514,7 +514,7 @@ var routeDescriptors = []RouteDescriptor{
|
||||
digestHeader,
|
||||
},
|
||||
Body: BodyDescriptor{
|
||||
ContentType: "application/json; charset=utf-8",
|
||||
ContentType: "<media type of manifest>",
|
||||
Format: manifestBody,
|
||||
},
|
||||
},
|
||||
@@ -553,7 +553,7 @@ var routeDescriptors = []RouteDescriptor{
|
||||
referenceParameterDescriptor,
|
||||
},
|
||||
Body: BodyDescriptor{
|
||||
ContentType: "application/json; charset=utf-8",
|
||||
ContentType: "<media type of manifest>",
|
||||
Format: manifestBody,
|
||||
},
|
||||
Successes: []ResponseDescriptor{
|
||||
|
2
vendor/github.com/docker/distribution/registry/api/v2/errors.go
generated
vendored
2
vendor/github.com/docker/distribution/registry/api/v2/errors.go
generated
vendored
@@ -84,7 +84,7 @@ var (
|
||||
})
|
||||
|
||||
// ErrorCodeManifestUnverified is returned when the manifest fails
|
||||
// signature verfication.
|
||||
// signature verification.
|
||||
ErrorCodeManifestUnverified = errcode.Register(errGroup, errcode.ErrorDescriptor{
|
||||
Value: "MANIFEST_UNVERIFIED",
|
||||
Message: "manifest failed signature verification",
|
||||
|
355
vendor/github.com/docker/distribution/registry/api/v2/routes_test.go
generated
vendored
355
vendor/github.com/docker/distribution/registry/api/v2/routes_test.go
generated
vendored
@@ -1,355 +0,0 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
type routeTestCase struct {
|
||||
RequestURI string
|
||||
ExpectedURI string
|
||||
Vars map[string]string
|
||||
RouteName string
|
||||
StatusCode int
|
||||
}
|
||||
|
||||
// TestRouter registers a test handler with all the routes and ensures that
|
||||
// each route returns the expected path variables. Not method verification is
|
||||
// present. This not meant to be exhaustive but as check to ensure that the
|
||||
// expected variables are extracted.
|
||||
//
|
||||
// This may go away as the application structure comes together.
|
||||
func TestRouter(t *testing.T) {
|
||||
testCases := []routeTestCase{
|
||||
{
|
||||
RouteName: RouteNameBase,
|
||||
RequestURI: "/v2/",
|
||||
Vars: map[string]string{},
|
||||
},
|
||||
{
|
||||
RouteName: RouteNameManifest,
|
||||
RequestURI: "/v2/foo/manifests/bar",
|
||||
Vars: map[string]string{
|
||||
"name": "foo",
|
||||
"reference": "bar",
|
||||
},
|
||||
},
|
||||
{
|
||||
RouteName: RouteNameManifest,
|
||||
RequestURI: "/v2/foo/bar/manifests/tag",
|
||||
Vars: map[string]string{
|
||||
"name": "foo/bar",
|
||||
"reference": "tag",
|
||||
},
|
||||
},
|
||||
{
|
||||
RouteName: RouteNameManifest,
|
||||
RequestURI: "/v2/foo/bar/manifests/sha256:abcdef01234567890",
|
||||
Vars: map[string]string{
|
||||
"name": "foo/bar",
|
||||
"reference": "sha256:abcdef01234567890",
|
||||
},
|
||||
},
|
||||
{
|
||||
RouteName: RouteNameTags,
|
||||
RequestURI: "/v2/foo/bar/tags/list",
|
||||
Vars: map[string]string{
|
||||
"name": "foo/bar",
|
||||
},
|
||||
},
|
||||
{
|
||||
RouteName: RouteNameTags,
|
||||
RequestURI: "/v2/docker.com/foo/tags/list",
|
||||
Vars: map[string]string{
|
||||
"name": "docker.com/foo",
|
||||
},
|
||||
},
|
||||
{
|
||||
RouteName: RouteNameTags,
|
||||
RequestURI: "/v2/docker.com/foo/bar/tags/list",
|
||||
Vars: map[string]string{
|
||||
"name": "docker.com/foo/bar",
|
||||
},
|
||||
},
|
||||
{
|
||||
RouteName: RouteNameTags,
|
||||
RequestURI: "/v2/docker.com/foo/bar/baz/tags/list",
|
||||
Vars: map[string]string{
|
||||
"name": "docker.com/foo/bar/baz",
|
||||
},
|
||||
},
|
||||
{
|
||||
RouteName: RouteNameBlob,
|
||||
RequestURI: "/v2/foo/bar/blobs/sha256:abcdef0919234",
|
||||
Vars: map[string]string{
|
||||
"name": "foo/bar",
|
||||
"digest": "sha256:abcdef0919234",
|
||||
},
|
||||
},
|
||||
{
|
||||
RouteName: RouteNameBlobUpload,
|
||||
RequestURI: "/v2/foo/bar/blobs/uploads/",
|
||||
Vars: map[string]string{
|
||||
"name": "foo/bar",
|
||||
},
|
||||
},
|
||||
{
|
||||
RouteName: RouteNameBlobUploadChunk,
|
||||
RequestURI: "/v2/foo/bar/blobs/uploads/uuid",
|
||||
Vars: map[string]string{
|
||||
"name": "foo/bar",
|
||||
"uuid": "uuid",
|
||||
},
|
||||
},
|
||||
{
|
||||
// support uuid proper
|
||||
RouteName: RouteNameBlobUploadChunk,
|
||||
RequestURI: "/v2/foo/bar/blobs/uploads/D95306FA-FAD3-4E36-8D41-CF1C93EF8286",
|
||||
Vars: map[string]string{
|
||||
"name": "foo/bar",
|
||||
"uuid": "D95306FA-FAD3-4E36-8D41-CF1C93EF8286",
|
||||
},
|
||||
},
|
||||
{
|
||||
RouteName: RouteNameBlobUploadChunk,
|
||||
RequestURI: "/v2/foo/bar/blobs/uploads/RDk1MzA2RkEtRkFEMy00RTM2LThENDEtQ0YxQzkzRUY4Mjg2IA==",
|
||||
Vars: map[string]string{
|
||||
"name": "foo/bar",
|
||||
"uuid": "RDk1MzA2RkEtRkFEMy00RTM2LThENDEtQ0YxQzkzRUY4Mjg2IA==",
|
||||
},
|
||||
},
|
||||
{
|
||||
// supports urlsafe base64
|
||||
RouteName: RouteNameBlobUploadChunk,
|
||||
RequestURI: "/v2/foo/bar/blobs/uploads/RDk1MzA2RkEtRkFEMy00RTM2LThENDEtQ0YxQzkzRUY4Mjg2IA_-==",
|
||||
Vars: map[string]string{
|
||||
"name": "foo/bar",
|
||||
"uuid": "RDk1MzA2RkEtRkFEMy00RTM2LThENDEtQ0YxQzkzRUY4Mjg2IA_-==",
|
||||
},
|
||||
},
|
||||
{
|
||||
// does not match
|
||||
RouteName: RouteNameBlobUploadChunk,
|
||||
RequestURI: "/v2/foo/bar/blobs/uploads/totalandcompletejunk++$$-==",
|
||||
StatusCode: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
// Check ambiguity: ensure we can distinguish between tags for
|
||||
// "foo/bar/image/image" and image for "foo/bar/image" with tag
|
||||
// "tags"
|
||||
RouteName: RouteNameManifest,
|
||||
RequestURI: "/v2/foo/bar/manifests/manifests/tags",
|
||||
Vars: map[string]string{
|
||||
"name": "foo/bar/manifests",
|
||||
"reference": "tags",
|
||||
},
|
||||
},
|
||||
{
|
||||
// This case presents an ambiguity between foo/bar with tag="tags"
|
||||
// and list tags for "foo/bar/manifest"
|
||||
RouteName: RouteNameTags,
|
||||
RequestURI: "/v2/foo/bar/manifests/tags/list",
|
||||
Vars: map[string]string{
|
||||
"name": "foo/bar/manifests",
|
||||
},
|
||||
},
|
||||
{
|
||||
RouteName: RouteNameManifest,
|
||||
RequestURI: "/v2/locahost:8080/foo/bar/baz/manifests/tag",
|
||||
Vars: map[string]string{
|
||||
"name": "locahost:8080/foo/bar/baz",
|
||||
"reference": "tag",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
checkTestRouter(t, testCases, "", true)
|
||||
checkTestRouter(t, testCases, "/prefix/", true)
|
||||
}
|
||||
|
||||
func TestRouterWithPathTraversals(t *testing.T) {
|
||||
testCases := []routeTestCase{
|
||||
{
|
||||
RouteName: RouteNameBlobUploadChunk,
|
||||
RequestURI: "/v2/foo/../../blob/uploads/D95306FA-FAD3-4E36-8D41-CF1C93EF8286",
|
||||
ExpectedURI: "/blob/uploads/D95306FA-FAD3-4E36-8D41-CF1C93EF8286",
|
||||
StatusCode: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
// Testing for path traversal attack handling
|
||||
RouteName: RouteNameTags,
|
||||
RequestURI: "/v2/foo/../bar/baz/tags/list",
|
||||
ExpectedURI: "/v2/bar/baz/tags/list",
|
||||
Vars: map[string]string{
|
||||
"name": "bar/baz",
|
||||
},
|
||||
},
|
||||
}
|
||||
checkTestRouter(t, testCases, "", false)
|
||||
}
|
||||
|
||||
func TestRouterWithBadCharacters(t *testing.T) {
|
||||
if testing.Short() {
|
||||
testCases := []routeTestCase{
|
||||
{
|
||||
RouteName: RouteNameBlobUploadChunk,
|
||||
RequestURI: "/v2/foo/blob/uploads/不95306FA-FAD3-4E36-8D41-CF1C93EF8286",
|
||||
StatusCode: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
// Testing for path traversal attack handling
|
||||
RouteName: RouteNameTags,
|
||||
RequestURI: "/v2/foo/不bar/tags/list",
|
||||
StatusCode: http.StatusNotFound,
|
||||
},
|
||||
}
|
||||
checkTestRouter(t, testCases, "", true)
|
||||
} else {
|
||||
// in the long version we're going to fuzz the router
|
||||
// with random UTF8 characters not in the 128 bit ASCII range.
|
||||
// These are not valid characters for the router and we expect
|
||||
// 404s on every test.
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
testCases := make([]routeTestCase, 1000)
|
||||
for idx := range testCases {
|
||||
testCases[idx] = routeTestCase{
|
||||
RouteName: RouteNameTags,
|
||||
RequestURI: fmt.Sprintf("/v2/%v/%v/tags/list", randomString(10), randomString(10)),
|
||||
StatusCode: http.StatusNotFound,
|
||||
}
|
||||
}
|
||||
checkTestRouter(t, testCases, "", true)
|
||||
}
|
||||
}
|
||||
|
||||
func checkTestRouter(t *testing.T, testCases []routeTestCase, prefix string, deeplyEqual bool) {
|
||||
router := RouterWithPrefix(prefix)
|
||||
|
||||
testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
testCase := routeTestCase{
|
||||
RequestURI: r.RequestURI,
|
||||
Vars: mux.Vars(r),
|
||||
RouteName: mux.CurrentRoute(r).GetName(),
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(w)
|
||||
|
||||
if err := enc.Encode(testCase); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
// Startup test server
|
||||
server := httptest.NewServer(router)
|
||||
|
||||
for _, testcase := range testCases {
|
||||
testcase.RequestURI = strings.TrimSuffix(prefix, "/") + testcase.RequestURI
|
||||
// Register the endpoint
|
||||
route := router.GetRoute(testcase.RouteName)
|
||||
if route == nil {
|
||||
t.Fatalf("route for name %q not found", testcase.RouteName)
|
||||
}
|
||||
|
||||
route.Handler(testHandler)
|
||||
|
||||
u := server.URL + testcase.RequestURI
|
||||
|
||||
resp, err := http.Get(u)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error issuing get request: %v", err)
|
||||
}
|
||||
|
||||
if testcase.StatusCode == 0 {
|
||||
// Override default, zero-value
|
||||
testcase.StatusCode = http.StatusOK
|
||||
}
|
||||
if testcase.ExpectedURI == "" {
|
||||
// Override default, zero-value
|
||||
testcase.ExpectedURI = testcase.RequestURI
|
||||
}
|
||||
|
||||
if resp.StatusCode != testcase.StatusCode {
|
||||
t.Fatalf("unexpected status for %s: %v %v", u, resp.Status, resp.StatusCode)
|
||||
}
|
||||
|
||||
if testcase.StatusCode != http.StatusOK {
|
||||
resp.Body.Close()
|
||||
// We don't care about json response.
|
||||
continue
|
||||
}
|
||||
|
||||
dec := json.NewDecoder(resp.Body)
|
||||
|
||||
var actualRouteInfo routeTestCase
|
||||
if err := dec.Decode(&actualRouteInfo); err != nil {
|
||||
t.Fatalf("error reading json response: %v", err)
|
||||
}
|
||||
// Needs to be set out of band
|
||||
actualRouteInfo.StatusCode = resp.StatusCode
|
||||
|
||||
if actualRouteInfo.RequestURI != testcase.ExpectedURI {
|
||||
t.Fatalf("URI %v incorrectly parsed, expected %v", actualRouteInfo.RequestURI, testcase.ExpectedURI)
|
||||
}
|
||||
|
||||
if actualRouteInfo.RouteName != testcase.RouteName {
|
||||
t.Fatalf("incorrect route %q matched, expected %q", actualRouteInfo.RouteName, testcase.RouteName)
|
||||
}
|
||||
|
||||
// when testing deep equality, the actualRouteInfo has an empty ExpectedURI, we don't want
|
||||
// that to make the comparison fail. We're otherwise done with the testcase so empty the
|
||||
// testcase.ExpectedURI
|
||||
testcase.ExpectedURI = ""
|
||||
if deeplyEqual && !reflect.DeepEqual(actualRouteInfo, testcase) {
|
||||
t.Fatalf("actual does not equal expected: %#v != %#v", actualRouteInfo, testcase)
|
||||
}
|
||||
|
||||
resp.Body.Close()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -------------- START LICENSED CODE --------------
|
||||
// The following code is derivative of https://github.com/google/gofuzz
|
||||
// gofuzz is licensed under the Apache License, Version 2.0, January 2004,
|
||||
// a copy of which can be found in the LICENSE file at the root of this
|
||||
// repository.
|
||||
|
||||
// These functions allow us to generate strings containing only multibyte
|
||||
// characters that are invalid in our URLs. They are used above for fuzzing
|
||||
// to ensure we always get 404s on these invalid strings
|
||||
type charRange struct {
|
||||
first, last rune
|
||||
}
|
||||
|
||||
// choose returns a random unicode character from the given range, using the
|
||||
// given randomness source.
|
||||
func (r *charRange) choose() rune {
|
||||
count := int64(r.last - r.first)
|
||||
return r.first + rune(rand.Int63n(count))
|
||||
}
|
||||
|
||||
var unicodeRanges = []charRange{
|
||||
{'\u00a0', '\u02af'}, // Multi-byte encoded characters
|
||||
{'\u4e00', '\u9fff'}, // Common CJK (even longer encodings)
|
||||
}
|
||||
|
||||
func randomString(length int) string {
|
||||
runes := make([]rune, length)
|
||||
for i := range runes {
|
||||
runes[i] = unicodeRanges[rand.Intn(len(unicodeRanges))].choose()
|
||||
}
|
||||
return string(runes)
|
||||
}
|
||||
|
||||
// -------------- END LICENSED CODE --------------
|
29
vendor/github.com/docker/distribution/registry/api/v2/urls.go
generated
vendored
29
vendor/github.com/docker/distribution/registry/api/v2/urls.go
generated
vendored
@@ -17,33 +17,35 @@ import (
|
||||
// under "/foo/v2/...". Most application will only provide a schema, host and
|
||||
// port, such as "https://localhost:5000/".
|
||||
type URLBuilder struct {
|
||||
root *url.URL // url root (ie http://localhost/)
|
||||
router *mux.Router
|
||||
root *url.URL // url root (ie http://localhost/)
|
||||
router *mux.Router
|
||||
relative bool
|
||||
}
|
||||
|
||||
// NewURLBuilder creates a URLBuilder with provided root url object.
|
||||
func NewURLBuilder(root *url.URL) *URLBuilder {
|
||||
func NewURLBuilder(root *url.URL, relative bool) *URLBuilder {
|
||||
return &URLBuilder{
|
||||
root: root,
|
||||
router: Router(),
|
||||
root: root,
|
||||
router: Router(),
|
||||
relative: relative,
|
||||
}
|
||||
}
|
||||
|
||||
// NewURLBuilderFromString workes identically to NewURLBuilder except it takes
|
||||
// a string argument for the root, returning an error if it is not a valid
|
||||
// url.
|
||||
func NewURLBuilderFromString(root string) (*URLBuilder, error) {
|
||||
func NewURLBuilderFromString(root string, relative bool) (*URLBuilder, error) {
|
||||
u, err := url.Parse(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewURLBuilder(u), nil
|
||||
return NewURLBuilder(u, relative), nil
|
||||
}
|
||||
|
||||
// NewURLBuilderFromRequest uses information from an *http.Request to
|
||||
// construct the root url.
|
||||
func NewURLBuilderFromRequest(r *http.Request) *URLBuilder {
|
||||
func NewURLBuilderFromRequest(r *http.Request, relative bool) *URLBuilder {
|
||||
var scheme string
|
||||
|
||||
forwardedProto := r.Header.Get("X-Forwarded-Proto")
|
||||
@@ -85,7 +87,7 @@ func NewURLBuilderFromRequest(r *http.Request) *URLBuilder {
|
||||
u.Path = requestPath[0 : index+1]
|
||||
}
|
||||
|
||||
return NewURLBuilder(u)
|
||||
return NewURLBuilder(u, relative)
|
||||
}
|
||||
|
||||
// BuildBaseURL constructs a base url for the API, typically just "/v2/".
|
||||
@@ -194,12 +196,13 @@ func (ub *URLBuilder) cloneRoute(name string) clonedRoute {
|
||||
*route = *ub.router.GetRoute(name) // clone the route
|
||||
*root = *ub.root
|
||||
|
||||
return clonedRoute{Route: route, root: root}
|
||||
return clonedRoute{Route: route, root: root, relative: ub.relative}
|
||||
}
|
||||
|
||||
type clonedRoute struct {
|
||||
*mux.Route
|
||||
root *url.URL
|
||||
root *url.URL
|
||||
relative bool
|
||||
}
|
||||
|
||||
func (cr clonedRoute) URL(pairs ...string) (*url.URL, error) {
|
||||
@@ -208,6 +211,10 @@ func (cr clonedRoute) URL(pairs ...string) (*url.URL, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cr.relative {
|
||||
return routeURL, nil
|
||||
}
|
||||
|
||||
if routeURL.Scheme == "" && routeURL.User == nil && routeURL.Host == "" {
|
||||
routeURL.Path = routeURL.Path[1:]
|
||||
}
|
||||
|
304
vendor/github.com/docker/distribution/registry/api/v2/urls_test.go
generated
vendored
304
vendor/github.com/docker/distribution/registry/api/v2/urls_test.go
generated
vendored
@@ -1,304 +0,0 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
)
|
||||
|
||||
type urlBuilderTestCase struct {
|
||||
description string
|
||||
expectedPath string
|
||||
build func() (string, error)
|
||||
}
|
||||
|
||||
func makeURLBuilderTestCases(urlBuilder *URLBuilder) []urlBuilderTestCase {
|
||||
fooBarRef, _ := reference.ParseNamed("foo/bar")
|
||||
return []urlBuilderTestCase{
|
||||
{
|
||||
description: "test base url",
|
||||
expectedPath: "/v2/",
|
||||
build: urlBuilder.BuildBaseURL,
|
||||
},
|
||||
{
|
||||
description: "test tags url",
|
||||
expectedPath: "/v2/foo/bar/tags/list",
|
||||
build: func() (string, error) {
|
||||
return urlBuilder.BuildTagsURL(fooBarRef)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "test manifest url",
|
||||
expectedPath: "/v2/foo/bar/manifests/tag",
|
||||
build: func() (string, error) {
|
||||
ref, _ := reference.WithTag(fooBarRef, "tag")
|
||||
return urlBuilder.BuildManifestURL(ref)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "build blob url",
|
||||
expectedPath: "/v2/foo/bar/blobs/sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5",
|
||||
build: func() (string, error) {
|
||||
ref, _ := reference.WithDigest(fooBarRef, "sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5")
|
||||
return urlBuilder.BuildBlobURL(ref)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "build blob upload url",
|
||||
expectedPath: "/v2/foo/bar/blobs/uploads/",
|
||||
build: func() (string, error) {
|
||||
return urlBuilder.BuildBlobUploadURL(fooBarRef)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "build blob upload url with digest and size",
|
||||
expectedPath: "/v2/foo/bar/blobs/uploads/?digest=sha256%3A3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5&size=10000",
|
||||
build: func() (string, error) {
|
||||
return urlBuilder.BuildBlobUploadURL(fooBarRef, url.Values{
|
||||
"size": []string{"10000"},
|
||||
"digest": []string{"sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5"},
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "build blob upload chunk url",
|
||||
expectedPath: "/v2/foo/bar/blobs/uploads/uuid-part",
|
||||
build: func() (string, error) {
|
||||
return urlBuilder.BuildBlobUploadChunkURL(fooBarRef, "uuid-part")
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "build blob upload chunk url with digest and size",
|
||||
expectedPath: "/v2/foo/bar/blobs/uploads/uuid-part?digest=sha256%3A3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5&size=10000",
|
||||
build: func() (string, error) {
|
||||
return urlBuilder.BuildBlobUploadChunkURL(fooBarRef, "uuid-part", url.Values{
|
||||
"size": []string{"10000"},
|
||||
"digest": []string{"sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5"},
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// TestURLBuilder tests the various url building functions, ensuring they are
|
||||
// returning the expected values.
|
||||
func TestURLBuilder(t *testing.T) {
|
||||
roots := []string{
|
||||
"http://example.com",
|
||||
"https://example.com",
|
||||
"http://localhost:5000",
|
||||
"https://localhost:5443",
|
||||
}
|
||||
|
||||
for _, root := range roots {
|
||||
urlBuilder, err := NewURLBuilderFromString(root)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error creating urlbuilder: %v", err)
|
||||
}
|
||||
|
||||
for _, testCase := range makeURLBuilderTestCases(urlBuilder) {
|
||||
url, err := testCase.build()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: error building url: %v", testCase.description, err)
|
||||
}
|
||||
|
||||
expectedURL := root + testCase.expectedPath
|
||||
|
||||
if url != expectedURL {
|
||||
t.Fatalf("%s: %q != %q", testCase.description, url, expectedURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestURLBuilderWithPrefix(t *testing.T) {
|
||||
roots := []string{
|
||||
"http://example.com/prefix/",
|
||||
"https://example.com/prefix/",
|
||||
"http://localhost:5000/prefix/",
|
||||
"https://localhost:5443/prefix/",
|
||||
}
|
||||
|
||||
for _, root := range roots {
|
||||
urlBuilder, err := NewURLBuilderFromString(root)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error creating urlbuilder: %v", err)
|
||||
}
|
||||
|
||||
for _, testCase := range makeURLBuilderTestCases(urlBuilder) {
|
||||
url, err := testCase.build()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: error building url: %v", testCase.description, err)
|
||||
}
|
||||
|
||||
expectedURL := root[0:len(root)-1] + testCase.expectedPath
|
||||
|
||||
if url != expectedURL {
|
||||
t.Fatalf("%s: %q != %q", testCase.description, url, expectedURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type builderFromRequestTestCase struct {
|
||||
request *http.Request
|
||||
base string
|
||||
}
|
||||
|
||||
func TestBuilderFromRequest(t *testing.T) {
|
||||
u, err := url.Parse("http://example.com")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
forwardedProtoHeader := make(http.Header, 1)
|
||||
forwardedProtoHeader.Set("X-Forwarded-Proto", "https")
|
||||
|
||||
forwardedHostHeader1 := make(http.Header, 1)
|
||||
forwardedHostHeader1.Set("X-Forwarded-Host", "first.example.com")
|
||||
|
||||
forwardedHostHeader2 := make(http.Header, 1)
|
||||
forwardedHostHeader2.Set("X-Forwarded-Host", "first.example.com, proxy1.example.com")
|
||||
|
||||
testRequests := []struct {
|
||||
request *http.Request
|
||||
base string
|
||||
configHost url.URL
|
||||
}{
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host},
|
||||
base: "http://example.com",
|
||||
},
|
||||
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host, Header: forwardedProtoHeader},
|
||||
base: "http://example.com",
|
||||
},
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host, Header: forwardedProtoHeader},
|
||||
base: "https://example.com",
|
||||
},
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host, Header: forwardedHostHeader1},
|
||||
base: "http://first.example.com",
|
||||
},
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host, Header: forwardedHostHeader2},
|
||||
base: "http://first.example.com",
|
||||
},
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host, Header: forwardedHostHeader2},
|
||||
base: "https://third.example.com:5000",
|
||||
configHost: url.URL{
|
||||
Scheme: "https",
|
||||
Host: "third.example.com:5000",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tr := range testRequests {
|
||||
var builder *URLBuilder
|
||||
if tr.configHost.Scheme != "" && tr.configHost.Host != "" {
|
||||
builder = NewURLBuilder(&tr.configHost)
|
||||
} else {
|
||||
builder = NewURLBuilderFromRequest(tr.request)
|
||||
}
|
||||
|
||||
for _, testCase := range makeURLBuilderTestCases(builder) {
|
||||
buildURL, err := testCase.build()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: error building url: %v", testCase.description, err)
|
||||
}
|
||||
|
||||
var expectedURL string
|
||||
proto, ok := tr.request.Header["X-Forwarded-Proto"]
|
||||
if !ok {
|
||||
expectedURL = tr.base + testCase.expectedPath
|
||||
} else {
|
||||
urlBase, err := url.Parse(tr.base)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
urlBase.Scheme = proto[0]
|
||||
expectedURL = urlBase.String() + testCase.expectedPath
|
||||
}
|
||||
|
||||
if buildURL != expectedURL {
|
||||
t.Fatalf("%s: %q != %q", testCase.description, buildURL, expectedURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuilderFromRequestWithPrefix(t *testing.T) {
|
||||
u, err := url.Parse("http://example.com/prefix/v2/")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
forwardedProtoHeader := make(http.Header, 1)
|
||||
forwardedProtoHeader.Set("X-Forwarded-Proto", "https")
|
||||
|
||||
testRequests := []struct {
|
||||
request *http.Request
|
||||
base string
|
||||
configHost url.URL
|
||||
}{
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host},
|
||||
base: "http://example.com/prefix/",
|
||||
},
|
||||
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host, Header: forwardedProtoHeader},
|
||||
base: "http://example.com/prefix/",
|
||||
},
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host, Header: forwardedProtoHeader},
|
||||
base: "https://example.com/prefix/",
|
||||
},
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host, Header: forwardedProtoHeader},
|
||||
base: "https://subdomain.example.com/prefix/",
|
||||
configHost: url.URL{
|
||||
Scheme: "https",
|
||||
Host: "subdomain.example.com",
|
||||
Path: "/prefix/",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tr := range testRequests {
|
||||
var builder *URLBuilder
|
||||
if tr.configHost.Scheme != "" && tr.configHost.Host != "" {
|
||||
builder = NewURLBuilder(&tr.configHost)
|
||||
} else {
|
||||
builder = NewURLBuilderFromRequest(tr.request)
|
||||
}
|
||||
|
||||
for _, testCase := range makeURLBuilderTestCases(builder) {
|
||||
buildURL, err := testCase.build()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: error building url: %v", testCase.description, err)
|
||||
}
|
||||
var expectedURL string
|
||||
proto, ok := tr.request.Header["X-Forwarded-Proto"]
|
||||
if !ok {
|
||||
expectedURL = tr.base[0:len(tr.base)-1] + testCase.expectedPath
|
||||
} else {
|
||||
urlBase, err := url.Parse(tr.base)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
urlBase.Scheme = proto[0]
|
||||
expectedURL = urlBase.String()[0:len(urlBase.String())-1] + testCase.expectedPath
|
||||
}
|
||||
|
||||
if buildURL != expectedURL {
|
||||
t.Fatalf("%s: %q != %q", testCase.description, buildURL, expectedURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user