revert the /stream etag, cache-control and 304
playback did not come back when x-audio-duration did, so the duration header was not the only thing i broke. the range and whole-file branches are byte-identical to the version that worked, which leaves these three as the only remaining difference on /stream. a cache that keeps a validator after evicting the body sends if-none-match, gets a 304 and has no audio. plausible, unproven, and not worth another round trip through someone's phone to find out — the etag was an optimisation and playback is not. /stream is now byte-identical to the last version known to play, verified by running both implementations side by side over no-range, closed, open and invalid ranges and diffing status, every header and body length. if-none-match is still accepted and ignored. re-introducing this needs a capture of what the player actually sends.
This commit is contained in:
+10
-5
@@ -30,8 +30,8 @@ Byte-range streaming so the player can **seek without downloading the whole file
|
||||
|
||||
| Case | Status | Headers |
|
||||
| --------------------- | ------ | --------------------------------------------------------------------------------------------- |
|
||||
| No `Range` | `200` | `Content-Type`, `Content-Length`, `Accept-Ranges: bytes`, `ETag`, `Cache-Control` |
|
||||
| With `Range: bytes=…` | `206` | `Content-Range`, `Content-Length`, `Accept-Ranges: bytes`, `Content-Type`, `ETag` |
|
||||
| No `Range` | `200` | `Content-Type`, `Content-Length`, `Accept-Ranges: bytes`, `X-Audio-Duration` |
|
||||
| With `Range: bytes=…` | `206` | `Content-Range`, `Content-Length`, `Accept-Ranges: bytes`, `Content-Type`, `X-Audio-Duration` |
|
||||
|
||||
- **`X-Audio-Duration` still ships, and no longer costs an `ffprobe`** (2026-08-19). It used to spawn
|
||||
one per file on the first request — measured at 50ms warm, 315ms cold, paid before the first byte.
|
||||
@@ -46,9 +46,14 @@ Byte-range streaming so the player can **seek without downloading the whole file
|
||||
`meta.json` is the fast path, not the only one: `/stream` serves any home-relative path and does not
|
||||
require indexing, so an unindexed album falls back to ffprobe (cached per file) rather than dropping
|
||||
the header. Absent only if ffprobe is missing or the file is unreadable — as before.
|
||||
- **`ETag`** is `mtime-size` in base36. A whole-file request with a matching `If-None-Match` answers
|
||||
`304`; a Range request never does, because a 304 would answer a question about part of a file with a
|
||||
statement about all of it.
|
||||
- **`/stream` has no `ETag` and no `Cache-Control`.** One was added on 2026-08-19 and removed the same
|
||||
day: the mobile player stopped playing, and after `X-Audio-Duration` was ruled out these headers were
|
||||
the only remaining difference from the version that worked. A cache that keeps a validator after
|
||||
evicting the body would send `If-None-Match`, receive `304`, and have no audio.
|
||||
|
||||
`If-None-Match` on `/stream` is therefore ignored — never `304`, always bytes. `/cover`, `/meta`,
|
||||
`/lyrics` and `/poster` DO have validators and are unaffected.
|
||||
|
||||
- Errors: `400` invalid/missing path · `404` not found · `416` bad range.
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user