A route this server does not implement answers 404 where upstream answers 401 #135
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
GET /Videos/{id}/live.m3u8anonymously: upstream 401, ours 404. Measured on the pair while closing #131.Upstream declares the whole of
DynamicHlsController[Authorize], so authorization runs before routing reaches an action — an anonymous caller is refused whether or not the route exists. Here an unimplemented route falls through to the router's own 404, which answers before any policy is consulted.The consequence is small but real: an unauthenticated caller can enumerate which routes this server implements by watching for 404 against 401. It is also a difference the harness reports on any scenario that names an unimplemented path anonymously.
The general question is bigger than the one route: for every controller upstream declares
[Authorize]at the class level, an unimplemented action of ours should refuse rather than 404 — andENDPOINTS.mdsays there are 85 documented operations this server does not answer, plus whatever undocumented ones sit beside them.Where to start
Work out which of upstream's class-level
[Authorize]controllers have actions this server does not implement —ENDPOINTS.mdis generated from exactly that comparison, so the list is already computable — then decide the shape. A per-module catch-all that refuses before falling through is one; a router-level rule keyed on the prefix is another, and the choice wants an argument inDECISIONS.mdbecause it is a deliberate difference from "everything unwritten is a 404".Care is needed not to break the opposite case: M8's whole point is that a route under an excluded feature answers the empty shape rather than a 404, and those must keep answering.
How to know it is done
An anonymous request for an unimplemented route under an authorized controller answers what upstream answers, and a scenario carries at least one —
refusals.jsonalready replays anonymously and is where it belongs.House rules
Tests run under
cargo nextest; upstream's source is the checkout inupstream/at the pin; generated artifacts are regenerated, never edited; comments say what the code does, not how it got there. The shared reference on:8096is read-only — a login is a write, so anything needing an account wants its own container from the pinned image over asqlite3 .backupcopy ofreference/var/config/data/jellyfin.db. Checkss -lntpfor a free port before binding; stale servers from earlier work are still listening.Folding this into #131 rather than tracking it separately — it came out of that work, it is the same module, and the fix belongs in the same branch. Reopening only if it turns out to be larger than that branch should carry.