Initial Commit
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
# range-response
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## 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
|
||||
|
||||
```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.
|
||||
Reference in New Issue
Block a user