diff --git a/src/Http/Request.php b/src/Http/Request.php index bc3da98..4d0e3a0 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 3142163..83ee138 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());