From 5ddf22386b7667515dc9e5aef5d01a2e08bb337b Mon Sep 17 00:00:00 2001 From: shimon Date: Wed, 26 Aug 2026 17:08:00 +0300 Subject: [PATCH] fix(request): accept single-byte ranges in parseRange RFC 9110 byte-range bounds are inclusive, so `bytes=0-0` (a one-byte range, commonly sent by Safari/iOS players probing range support) and a request for a file's final byte are valid. parseRange() rejected any range where start >= end, so these requests parsed as no-range and consumers answered 416. Only start > end is invalid. Co-Authored-By: Claude Opus 4.8 --- src/Http/Request.php | 4 +++- tests/RequestTest.php | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Http/Request.php b/src/Http/Request.php index bc3da980..4d0e3a00 100755 --- a/src/Http/Request.php +++ b/src/Http/Request.php @@ -712,7 +712,9 @@ protected function parseRange(): ?array $data['end'] = (int) $ranges[1]; } - if ($data['end'] !== null && $data['start'] >= $data['end']) { + // RFC 9110 range bounds are inclusive, so start === end is a valid + // single-byte range (`bytes=0-0`, or the final byte of a file). + if ($data['end'] !== null && $data['start'] > $data['end']) { return null; } diff --git a/tests/RequestTest.php b/tests/RequestTest.php index 3142163d..83ee1388 100755 --- a/tests/RequestTest.php +++ b/tests/RequestTest.php @@ -340,6 +340,26 @@ public function testCanGetRange(): void $this->assertSame(0, $this->request->getRangeStart()); $this->assertNull($this->request->getRangeEnd()); + // RFC 9110 bounds are inclusive: start === end is a valid single-byte range. + $_SERVER['HTTP_RANGE'] = 'bytes=0-0'; + $this->request = new Request(); + $this->assertSame('bytes', $this->request->getRangeUnit()); + $this->assertSame(0, $this->request->getRangeStart()); + $this->assertSame(0, $this->request->getRangeEnd()); + + $_SERVER['HTTP_RANGE'] = 'bytes=499-499'; + $this->request = new Request(); + $this->assertSame('bytes', $this->request->getRangeUnit()); + $this->assertSame(499, $this->request->getRangeStart()); + $this->assertSame(499, $this->request->getRangeEnd()); + + // Start past end is still invalid. + $_SERVER['HTTP_RANGE'] = 'bytes=5-4'; + $this->request = new Request(); + $this->assertNull($this->request->getRangeUnit()); + $this->assertNull($this->request->getRangeStart()); + $this->assertNull($this->request->getRangeEnd()); + $_SERVER['HTTP_RANGE'] = 'bytes=0--499'; $this->request = new Request(); $this->assertNull($this->request->getRangeUnit());