Files
linearvoid/infrastructure/cloudflare/README.md
T
zwitschi 8c5e70959b feat(cloudflare): add linearvoid-media edge worker for R2 HLS delivery
Replace the ad-hoc `worker.js` with a self-contained `linearvoid-media`
worker under `infrastructure/cloudflare/` that owns `media.linearvoid.tv`.
It serves HLS objects from the R2 bucket, enforcing immutable Cache-Control
on segments, a short TTL on live manifests, plus HLS CORS, OPTIONS
preflight, Range support, and a `/health` probe. Includes wrapper config
with production domain, Vitest unit tests, Miniflare R2 integration tests,
automated deploy workflow, and docs updates.
2026-09-03 08:52:31 +02:00

2.3 KiB

linearvoid-media Worker

Cloudflare Worker that owns media.linearvoid.tv and serves the HLS objects stored in the linearvoid-media R2 bucket, applying the edge cache policy in code:

Object Cache-Control
.m4s / .ts / .mp4 / .m4a (segments) public, max-age=31536000, immutable
.m3u8 (live manifest) public, max-age=1, s-maxage=2, must-revalidate

It also adds HLS CORS (Access-Control-Allow-Origin: *), OPTIONS preflight, a /health probe, and Range-request support. This worker replaces direct R2 custom-domain serving on the media host so cache headers/CORS are controlled in code (cache rules on the same host remain the origin baseline).

Layout

infrastructure/cloudflare/
├── wrangler.toml        # name/binding + production custom-domain route
├── package.json
├── src/worker.js        # worker module (exports default.fetch + pure helpers)
└── test/                # Vitest unit tests + Miniflare (workerd) R2 tests

Local dev / test

cd infrastructure/cloudflare
npm install
npm test                 # unit + Miniflare R2 integration tests
npx wrangler dev         # run locally against your account's R2 bucket

Deploy

Preview / test target (default environment → *.workers.dev):

cd infrastructure/cloudflare
npx wrangler deploy

Production (attaches media.linearvoid.tv as a custom domain on this worker):

cd infrastructure/cloudflare
npx wrangler deploy --env production

Both need CLOUDFLARE_API_TOKEN (Workers Scripts/Routes edit) and CLOUDFLARE_ACCOUNT_ID in the environment. The media host must first be removed from the R2 bucket's direct custom-domain binding, otherwise the route collides.

Automated production deploys run via .gitea/workflows/workers-media-deploy.yml after CI succeeds on main.

Verify

curl -I https://media.linearvoid.tv/hls/playlist.m3u8   # short TTL
curl -I https://media.linearvoid.tv/hls/<segment>.m4s   # immutable + CORS
curl https://media.linearvoid.tv/health                 # {"status":"ok",...}