Parsing HTTP_RANGE header in PHP
Asked Answered
H

3

10

Is there an existing way to parse the HTTP_RANGE header correctly in PHP? Thought I'd ask here before re-inventing the wheel.

I am currently using

preg_match('/bytes=(\d+)-(\d+)/', $_SERVER['HTTP_RANGE'], $matches);

to parse the header but that does not cover all possible values of the header so I am wondering if there is a function or library that can do this already?

Thanks in advance.

Huff answered 5/2, 2010 at 17:52 Comment(1)
I don't know of a way to do this, but I'd have a crack at it with regular expressions. Take a look at the specification tools.ietf.org/html/draft-ietf-http-range-retrieval-00Leishmaniasis
U
10

Rather use regex to test it before sending a 416. Then just parse it by exploding on the comma , and the hyphen -. I also see that you used \d+ in your regex, but those are actually not required. When either of the range indexes is omitted, then it just means "first byte" or "last byte". You should cover that in your regex as well. Also see the Range header in the HTTP spec how you're supposed to handle it.

Kickoff example:

if (isset($_SERVER['HTTP_RANGE'])) {
    if (!preg_match('^bytes=\d*-\d*(,\d*-\d*)*$', $_SERVER['HTTP_RANGE'])) {
        header('HTTP/1.1 416 Requested Range Not Satisfiable');
        header('Content-Range: bytes */' . filelength); // Required in 416.
        exit;
    }

    $ranges = explode(',', substr($_SERVER['HTTP_RANGE'], 6));
    foreach ($ranges as $range) {
        $parts = explode('-', $range);
        $start = $parts[0]; // If this is empty, this should be 0.
        $end = $parts[1]; // If this is empty or greater than than filelength - 1, this should be filelength - 1.

        if ($start > $end) {
            header('HTTP/1.1 416 Requested Range Not Satisfiable');
            header('Content-Range: bytes */' . filelength); // Required in 416.
            exit;
        }

        // ...
    }
}

Edit: $start must always be less than $end

Ulster answered 6/2, 2010 at 3:21 Comment(3)
You're welcome. Disclaimer: untested. This is less or more translated in head from my Java Servlet example here: balusc.blogspot.com/2009/02/…Ulster
The RFC specification for byte ranges also allows something like bytes=-500 which is a valid request for the last 500 bytes of a file. This makes it a bit more complicated to extract the range than just exploding on the - character.Hotpress
This answer is wrong when it states that when start is missing it should be treated as 0. As Andrew Theis said, when you see something like bytes=-500, it's a request for the end of the file, NOT bytes=0-500.Kevyn
U
2

Taken from the PEAR Package HTTP_Download:

function getRanges()
{
    return preg_match('/^bytes=((\d*-\d*,? ?)+)$/', @$_SERVER['HTTP_RANGE'], $matches) ? $matches[1] : array();
}

It is also a good idea to use this packages for stuff like this!

Umbilicate answered 6/2, 2010 at 13:35 Comment(0)
G
1

There's a snippet implementing HTTP range support on the fread() page:

http://www.php.net/manual/en/function.fread.php#84115

Gramps answered 5/2, 2010 at 21:45 Comment(1)
This helps, but it's buggy. Use as a guide only.Maxwell

© 2022 - 2024 — McMap. All rights reserved.