Add limited support for 416 Requested Range Not Satisfiable

This commit is contained in:
Zach Borboa
2016-11-11 00:23:26 -08:00
parent e38820a5a3
commit d8808daf7a
2 changed files with 48 additions and 24 deletions
+14 -7
View File
@@ -8,8 +8,6 @@ class ContentRangeServer
{
public function serve($path)
{
$range = new RangeHeader($_SERVER['HTTP_RANGE']);
$filesize = filesize($path);
$fp = fopen($path, 'r');
@@ -19,16 +17,25 @@ class ContentRangeServer
header('Accept-Ranges: bytes');
fpassthru($fp);
} else {
header('HTTP/1.1 206 Partial Content');
header('Content-Length: ' . $range->getLength($filesize));
header('Content-Range: ' . $range->getContentRangeHeader($filesize));
$range = new RangeHeader($_SERVER['HTTP_RANGE'], $path);
$start = $range->getFirstBytePosition($filesize);
if (!$range->isValid()) {
header('HTTP/1.1 416 Requested Range Not Satisfiable');
header('Content-Range: ' . $range->getContentRangeHeader());
exit;
}
$length = $range->getLength();
header('HTTP/1.1 206 Partial Content');
header('Content-Length: ' . $length);
header('Content-Range: ' . $range->getContentRangeHeader());
$start = $range->getFirstBytePosition();
if ($start > 0) {
fseek($fp, $start, SEEK_SET);
}
$length = $range->getLength($filesize);
$chunk_size = 4096;
while ($length) {
$read = $length > $chunk_size ? $chunk_size : $length;
+34 -17
View File
@@ -6,48 +6,65 @@ class RangeHeader
{
private $first_byte;
private $last_byte;
private $filesize;
private $is_valid = true;
public function __construct($http_range_header)
public function __construct($http_range_header, $file_path)
{
// Simulate basic support for the Content-Range header.
preg_match('/bytes=(\d+)?-(\d+)?/', $http_range_header, $matches);
$this->first_byte = isset($matches['1']) ? (int)$matches['1'] : null;
$this->last_byte = isset($matches['2']) ? (int)$matches['2'] : null;
$this->filesize = filesize($file_path);
// Start position begins after end of file.
if ($this->first_byte >= $this->filesize) {
$this->is_valid = false;
}
// "If the last-byte-pos value is present, it MUST be greater than or equal to the first-byte-pos in that
// byte-range-spec, or the byte- range-spec is syntactically invalid."
if (!($this->last_byte === null) && !($this->last_byte >= $this->first_byte)) {
$this->is_valid = false;
}
}
public function getFirstBytePosition($file_size)
public function getFirstBytePosition()
{
$size = (int)$file_size;
if ($this->first_byte === null) {
return $size - 1 - $this->last_byte;
return $this->filesize - 1 - $this->last_byte;
}
return $this->first_byte;
}
public function getLastBytePosition($file_size)
public function getLastBytePosition()
{
$size = (int)$file_size;
if ($this->last_byte === null) {
return $size - 1;
return $this->filesize - 1;
}
return $this->last_byte;
}
public function getLength($file_size)
public function getLength()
{
$size = (int)$file_size;
return $this->getLastBytePosition($size) - $this->getFirstBytePosition($size) + 1;
return $this->getLastBytePosition() - $this->getFirstBytePosition() + 1;
}
public function getContentRangeHeader($file_size)
public function getByteRangeSpec()
{
return
'bytes ' . $this->getFirstBytePosition($file_size) . '-' . $this->getLastBytePosition($file_size) . '/' .
$file_size;
return $this->is_valid ? $this->getFirstBytePosition() . '-' . $this->getLastBytePosition() : '*';
}
public function getContentRangeHeader()
{
return 'bytes ' . $this->getByteRangeSpec() . '/' . $this->filesize;
}
public function isValid()
{
return $this->is_valid;
}
}