Skip to content

Support HTTP byte-range requests for cached artifact downloads #344

Description

@abhinavgautam01

Summary

Add HTTP byte-range support to locally served cached artifacts so clients can resume interrupted downloads without transferring the entire file again. This is particularly useful for large OCI blobs, Python wheels and generic release assets.

Affected code

  • internal/handler/handler.go: serveArtifact and its callers
  • internal/handler/generic.go: release-asset response handling
  • internal/handler/container.go: cached OCI blob response handling
  • Storage reader interfaces, if efficient seeking or ranged reads require backend support

Current behavior

The shared artifact-serving path receives the HTTP method rather than the full request. It does not inspect Range or If-Range, does not advertise byte-range support and streams the complete artifact with 200 OK.

A client attempting to resume an interrupted download therefore receives the whole representation again. Depending on the client, it must restart the download or report that resuming is unsupported.

Ignoring range requests is permitted by HTTP, so this is an enhancement rather than a protocol-compliance bug. It nevertheless imposes avoidable bandwidth and I/O costs on users downloading large cached files.

Expected behavior

For cached artifacts that the proxy can serve with reliable size and range access:

  • Advertise Accept-Ranges: bytes.
  • Honor supported byte ranges with 206 Partial Content, the correct Content-Range and the length of the selected bytes.
  • Support bounded, open-ended and suffix ranges.
  • Return 416 Range Not Satisfiable with Content-Range: bytes */<size> for a valid but unsatisfiable range.
  • Respect If-Range: serve the full representation when the supplied validator does not match.
  • Preserve ordinary full-download and HEAD behavior, including sending no body for HEAD.

Suggested implementation

Pass the request, or its relevant headers, into the artifact-serving layer. Prefer standard HTTP serving helpers where the storage reader supports their seeking requirements.

For non-seekable object-storage readers, consider backend ranged reads. Reading and discarding a large prefix can produce a correct response but does not provide the same storage-I/O savings. Avoid buffering whole large artifacts in memory merely to support seeking.

Define multi-range handling explicitly: either implement multipart responses or safely ignore unsupported multi-range requests and serve the complete representation. Do not silently interpret a multi-range request as a different single range. Only advertise range support on paths that actually implement it; direct-storage redirects remain subject to the destination's capabilities.

Acceptance tests

  • Request a bounded range and verify status, headers and exact response bytes.
  • Exercise open-ended and suffix ranges, including a suffix larger than the artifact.
  • Request a range starting at or beyond the end of the artifact and verify 416.
  • Verify matching and mismatching If-Range validators.
  • Verify no-range requests still return the full artifact and HEAD never sends a body.
  • Cover the chosen malformed-range and multi-range behavior.
  • Cover supported storage reader types and ensure cached range requests do not re-download the artifact from upstream.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions