# 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=-` 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 */` 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 ```ts 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 ```ts 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.