diff --git a/src/common/utils/registry/repository.go b/src/common/utils/registry/repository.go index b3cbc7473..adef72860 100644 --- a/src/common/utils/registry/repository.go +++ b/src/common/utils/registry/repository.go @@ -377,7 +377,11 @@ func (r *Repository) initiateBlobUpload(name string) (location, uploadUUID strin } func (r *Repository) monolithicBlobUpload(location, digest string, size int64, data io.Reader) error { - req, err := http.NewRequest("PUT", buildMonolithicBlobUploadURL(location, digest), data) + url, err := buildMonolithicBlobUploadURL(r.Endpoint.String(), location, digest) + if err != nil { + return err + } + req, err := http.NewRequest("PUT", url, data) if err != nil { return err } @@ -462,7 +466,16 @@ func buildInitiateBlobUploadURL(endpoint, repoName string) string { return fmt.Sprintf("%s/v2/%s/blobs/uploads/", endpoint, repoName) } -func buildMonolithicBlobUploadURL(location, digest string) string { +func buildMonolithicBlobUploadURL(endpoint, location, digest string) (string, error) { + relative, err := isRelativeURL(location) + if err != nil { + return "", err + } + // when the registry enables "relativeurls", the location returned + // has no scheme and host part + if relative { + location = endpoint + location + } query := "" if strings.ContainsRune(location, '?') { query = "&" @@ -470,5 +483,13 @@ func buildMonolithicBlobUploadURL(location, digest string) string { query = "?" } query += fmt.Sprintf("digest=%s", digest) - return fmt.Sprintf("%s%s", location, query) + return fmt.Sprintf("%s%s", location, query), nil +} + +func isRelativeURL(endpoint string) (bool, error) { + u, err := url.Parse(endpoint) + if err != nil { + return false, err + } + return !u.IsAbs(), nil } diff --git a/src/common/utils/registry/repository_test.go b/src/common/utils/registry/repository_test.go index 753504441..8bdbe60ff 100644 --- a/src/common/utils/registry/repository_test.go +++ b/src/common/utils/registry/repository_test.go @@ -24,6 +24,10 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" + + "github.com/stretchr/testify/require" + "github.com/docker/distribution/manifest/schema2" registry_error "github.com/vmware/harbor/src/common/utils/error" "github.com/vmware/harbor/src/common/utils/test" @@ -399,3 +403,22 @@ func TestParseError(t *testing.T) { func newRepository(endpoint string) (*Repository, error) { return NewRepository(repository, endpoint, &http.Client{}) } + +func TestBuildMonolithicBlobUploadURL(t *testing.T) { + endpoint := "http://192.169.0.1" + digest := "sha256:ef15416724f6e2d5d5b422dc5105add931c1f2a45959cd4993e75e47957b3b55" + + // absolute URL + location := "http://192.169.0.1/v2/library/golang/blobs/uploads/c9f84fd7-0198-43e3-80a7-dd13771cd7f0?_state=GabyCujPu0dpxiY8yYZTq" + expected := location + "&digest=" + digest + url, err := buildMonolithicBlobUploadURL(endpoint, location, digest) + require.Nil(t, err) + assert.Equal(t, expected, url) + + // relative URL + location = "/v2/library/golang/blobs/uploads/c9f84fd7-0198-43e3-80a7-dd13771cd7f0?_state=GabyCujPu0dpxiY8yYZTq" + expected = endpoint + location + "&digest=" + digest + url, err = buildMonolithicBlobUploadURL(endpoint, location, digest) + require.Nil(t, err) + assert.Equal(t, expected, url) +}