diff --git a/backend/src/handlers/upload.rs b/backend/src/handlers/upload.rs index 7e232bb..6c1ac71 100644 --- a/backend/src/handlers/upload.rs +++ b/backend/src/handlers/upload.rs @@ -647,12 +647,95 @@ pub async fn compute_storage_quota(state: &AppState) -> QuotaEstimate { } } +/// Outcome of parsing a `Range` request header against a known file length. +#[derive(Debug, PartialEq, Eq)] +enum RangeSpec { + /// No `Range` header, or one we deliberately don't honour (multi-range, non-`bytes` + /// unit, malformed). RFC 9110 lets a server ignore a Range it can't process and reply + /// 200 with the full body, which is what every one of these cases does. + Full, + /// A single satisfiable range, resolved to inclusive absolute offsets. + Partial { start: u64, end: u64 }, + /// Syntactically valid but starts beyond EOF — must be answered 416, not 200, or a + /// player can loop re-requesting it. + Unsatisfiable, +} + +/// Parse a single-range `bytes=` header against `len`. +/// +/// Deliberately supports only the three forms a media element actually sends — +/// `bytes=N-`, `bytes=N-M`, `bytes=-S` (suffix) — and treats everything else as `Full`. +/// Multi-range responses need `multipart/byteranges`, which no `