Skip to content

Commit

Permalink
fix: attempt range query only if server explicitly supports (#369)
Browse files Browse the repository at this point in the history
Fixes #368

Signed-off-by: Shiwei Zhang <shizh@microsoft.com>
  • Loading branch information
shizhMSFT authored Dec 2, 2022
1 parent 511e4d4 commit 7dcd097
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 24 deletions.
1 change: 1 addition & 0 deletions registry/remote/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ func TestMain(m *testing.M) {
case p == fmt.Sprintf("/v2/%s/blobs/%s", exampleRepositoryName, exampleLayerDigest):
w.Header().Set("Content-Type", ocispec.MediaTypeImageLayer)
w.Header().Set("Docker-Content-Digest", string(exampleLayerDigest))
w.Header().Set("Accept-Ranges", "bytes")
var start, end = 0, len(exampleLayer) - 1
if h := r.Header.Get("Range"); h != "" {
w.WriteHeader(http.StatusPartialContent)
Expand Down
39 changes: 16 additions & 23 deletions registry/remote/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -623,14 +623,6 @@ func (s *blobStore) Fetch(ctx context.Context, target ocispec.Descriptor) (rc io
return nil, err
}

// probe server range request ability.
// Docker spec allows range header form of "Range: bytes=<start>-<end>".
// However, the remote server may still not RFC 7233 compliant.
// Reference: https://docs.docker.com/registry/spec/api/#blob
if target.Size > 0 {
req.Header.Set("Range", fmt.Sprintf("bytes=0-%d", target.Size-1))
}

resp, err := s.repo.client().Do(req)
if err != nil {
return nil, err
Expand All @@ -646,9 +638,15 @@ func (s *blobStore) Fetch(ctx context.Context, target ocispec.Descriptor) (rc io
if size := resp.ContentLength; size != -1 && size != target.Size {
return nil, fmt.Errorf("%s %q: mismatch Content-Length", resp.Request.Method, resp.Request.URL)
}

// check server range request capability.
// Docker spec allows range header form of "Range: bytes=<start>-<end>".
// However, the remote server may still not RFC 7233 compliant.
// Reference: https://docs.docker.com/registry/spec/api/#blob
if rangeUnit := resp.Header.Get("Accept-Ranges"); rangeUnit == "bytes" {
return httputil.NewReadSeekCloser(s.repo.client(), req, resp.Body, target.Size), nil
}
return resp.Body, nil
case http.StatusPartialContent:
return httputil.NewReadSeekCloser(s.repo.client(), req, resp.Body, target.Size), nil
case http.StatusNotFound:
return nil, fmt.Errorf("%s: %w", target.Digest, errdef.ErrNotFound)
default:
Expand Down Expand Up @@ -808,13 +806,6 @@ func (s *blobStore) FetchReference(ctx context.Context, reference string) (desc
return ocispec.Descriptor{}, nil, err
}

// probe server range request ability.
// Docker spec allows range header form of "Range: bytes=<start>-<end>".
// The form of "Range: bytes=<start>-" is also acceptable.
// However, the remote server may still not RFC 7233 compliant.
// Reference: https://docs.docker.com/registry/spec/api/#blob
req.Header.Set("Range", "bytes=0-")

resp, err := s.repo.client().Do(req)
if err != nil {
return ocispec.Descriptor{}, nil, err
Expand All @@ -831,13 +822,15 @@ func (s *blobStore) FetchReference(ctx context.Context, reference string) (desc
if err != nil {
return ocispec.Descriptor{}, nil, err
}
return desc, resp.Body, nil
case http.StatusPartialContent:
desc, err = generateBlobDescriptor(resp, refDigest)
if err != nil {
return ocispec.Descriptor{}, nil, err

// check server range request capability.
// Docker spec allows range header form of "Range: bytes=<start>-<end>".
// However, the remote server may still not RFC 7233 compliant.
// Reference: https://docs.docker.com/registry/spec/api/#blob
if rangeUnit := resp.Header.Get("Accept-Ranges"); rangeUnit == "bytes" {
return desc, httputil.NewReadSeekCloser(s.repo.client(), req, resp.Body, desc.Size), nil
}
return desc, httputil.NewReadSeekCloser(s.repo.client(), req, resp.Body, desc.Size), nil
return desc, resp.Body, nil
case http.StatusNotFound:
return ocispec.Descriptor{}, nil, fmt.Errorf("%s: %w", ref, errdef.ErrNotFound)
default:
Expand Down
7 changes: 6 additions & 1 deletion registry/remote/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import (
)

type testIOStruct struct {
name string
isTag bool
clientSuppliedReference string
serverCalculatedDigest digest.Digest // for non-HEAD (body-containing) requests only
Expand Down Expand Up @@ -1967,6 +1966,9 @@ func Test_BlobStore_Fetch_Seek(t *testing.T) {
case "/v2/test/blobs/" + blobDesc.Digest.String():
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Docker-Content-Digest", blobDesc.Digest.String())
if seekable {
w.Header().Set("Accept-Ranges", "bytes")
}
rangeHeader := r.Header.Get("Range")
if !seekable || rangeHeader == "" {
w.WriteHeader(http.StatusOK)
Expand Down Expand Up @@ -2487,6 +2489,9 @@ func Test_BlobStore_FetchReference_Seek(t *testing.T) {
case "/v2/test/blobs/" + blobDesc.Digest.String():
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Docker-Content-Digest", blobDesc.Digest.String())
if seekable {
w.Header().Set("Accept-Ranges", "bytes")
}
rangeHeader := r.Header.Get("Range")
if !seekable || rangeHeader == "" {
w.WriteHeader(http.StatusOK)
Expand Down

0 comments on commit 7dcd097

Please sign in to comment.