Files
2026-05-27 23:47:53 +01:00

3.7 KiB

range-response

(no submodules)

Purpose

RFC 7233 §2.1 single-range Response builder for packed-resource delivery from the Service Worker. Browsers ask for ranges when streaming audio, scrubbing video, or resuming a download — this module is the helper the SW invokes to serve those ranges out of the already-decoded bytes it cached. The helper keeps SW code small: parse, branch, build Response. No state, no allocations beyond the response body slice.

Features

  • Single-range bytes=<start>-<end> parsing with normalised open-ended (bytes=100-) and suffix (bytes=-100) forms.
  • 206 Partial Content with Content-Range, Accept-Ranges: bytes, and Content-Length headers when the request is a valid single range above the configured threshold.
  • 200 OK with Accept-Ranges: bytes for unranged requests or bodies below the threshold (default 256 KiB).
  • 416 Range Not Satisfiable for multi-range or malformed ranges, with a Content-Range: bytes */<total> header per spec.
  • 412 Precondition Failed for If-Range ETag mismatches.
  • Accept-Ranges: bytes advertised on every successful response so clients know the resource supports ranges going forward.

Usage: Basic Example

import { serveRangeResponse } from "@suaveplan/packer-browser";

self.addEventListener("fetch", (event) => {
    const req = (event as FetchEvent).request;
    const body = getCachedBody(req); // application-specific
    (event as FetchEvent).respondWith(
        serveRangeResponse(req, body, { contentType: "audio/mpeg" })
    );
});

Usage: Advanced Example

import {
    serveRangeResponse,
    DEFAULT_RANGE_THRESHOLD_BYTES,
} from "@suaveplan/packer-browser";

function buildResponse(req: Request, body: Uint8Array, etag: string) {
    return serveRangeResponse(req, body, {
        contentType: "video/mp4",
        etag,
        // Lower the threshold for small clips that benefit from range
        // hopping (e.g. sprite-sheet image maps).
        rangeThreshold: DEFAULT_RANGE_THRESHOLD_BYTES / 8,
    });
}

API Reference

  • parseRange(header: string | null, totalBytes: number): ParseRangeResult
    • Returns null when header is absent or non-bytes unit.
    • Returns "multi-range" when the header carries more than one range.
    • Returns "invalid" when malformed or out-of-bounds.
    • Returns ParsedByteRange { start, end } otherwise.
  • serveRangeResponse(request: Request, body: Uint8Array, opts?: ServeRangeResponseOptions): Response
    • opts.contentType — defaults to application/octet-stream.
    • opts.etag — when present, enables If-Range evaluation.
    • opts.rangeThreshold — minimum body size to enable 206 (default 262144).
  • DEFAULT_RANGE_THRESHOLD_BYTES: number — 262144.

Implementation Notes

  • The 256 KiB default threshold is chosen empirically: below this size the cost of slicing + emitting a 206 outweighs the saving for typical consumers (a single round-trip with the full body is cheaper). The threshold is fully configurable via RunServiceWorkerOptions.rangeThreshold.
  • The helper does NOT support multi-range responses (multipart/byteranges). RFC 7233 explicitly permits servers to return either 416 or fall back to 200; this implementation chooses 416 to surface the limit immediately so clients can issue single-range follow-ups.
  • If-Range is interpreted as strong ETag equality. Date-based If-Range values are treated as etags and will mismatch any configured etag; callers that want HTTP-date semantics should set opts.etag to the date string they expect.
  • Every successful response advertises Accept-Ranges: bytes, even the below-threshold 200, so the next client request can choose to issue a ranged follow-up.