Skip to content

feat(download): client-side HTTP Range / byte-offset resume #452

Description

@rejifald

Deferred by design from #451 (initial @stitchapi/download release). Byte-offset resume — reconnecting a dropped download from where it stopped instead of re-fetching from byte 0 — is unimplemented on the client side.

What already exists

  • Server-side rig primitives (packages/core/test/support/mock-server.ts): serveRange206 Partial Content + correct Content-Range; forceStatusOnRange: 416 | 200 (unsatisfiable / ignore-Range trap); etag / lastModified / acceptRanges validators — built as scaffolding for exactly this.
  • Core download() is a buffered surface that never sends Range; its interpret rejects non-200/204 (a stray 206 fails today — M1).

Why it's new code, not a rewire

Verified: the SSE resume seams (resumeToken/applyResume) fire only for a surface with a stream hook, so they do not apply to the buffered download surface.

Proposal (per ADR 0005, in @stitchapi/download wrapping download())

  • buildRequest: inject Range: bytes=N- on a resumed attempt.
  • interpret: branch 206 (continue) / 200 (server ignored Range → discard partial, restart) / 416 (done-or-restart, never infinite-retry the same Range).
  • If-Range: guard with a strong ETag or Last-Modified (never a weak ETag); a changed validator ⇒ 200 full body ⇒ discard the stale partial and restart (never stitch two generations together).
  • Refuse byte-offset resume when the response Content-Encoding is a real coding (gate on response CE, not the Accept-Encoding sent).

References

Rig spec §2.4 (R1–R16), oracles §4, cell X22. The client-side resume assertions (R6–R16) are already gated in the rig, waiting on this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions