6

I sometimes get an error on my Node.js server telling me req.headers.range is undefined when a user is requesting a .mp4 (I haven't tried serving any other video filetypes, not sure if mp4 is relevant). I don't understand why this header is missing.

Should a request header for a video sometimes exclude range?

I send the stream like this:

var videoReqHandler = function(req, res, pathname) {

    var file = dirPath + "/Client" + pathname;
    var range = req.headers.range;
    var positions = range.replace(/bytes=/, "").split("-");
    var start = parseInt(positions[0], 10);

    fs.stat(file, function(err, stats) {
        if (err) {
            throw err;
        } else {
            var total = stats.size;
            var end = positions[1] ? parseInt(positions[1], 10) : total - 1;
            var chunksize = (end - start) + 1;
            res.writeHead(206, {
                "Content-Range" : "bytes " + start + "-" + end + "/" + total,
                "Accept-Ranges" : "bytes",
                "Content-Length" : chunksize,
                "Content-Type" : "video/mp4"
            });
            var stream = fs.createReadStream(file, {
                start : start,
                end : end
            }).on("open", function() {
                stream.pipe(res);
            }).on("error", function(err) {
                res.end(err);
            });
        }
    });
};

The error:

/video_stream.js:21
        var positions = range.replace(/bytes=/, "").split("-");
        TypeError: Cannot call method 'replace' of undefined

3 Answers3

6

The Range header is optional:

HTTP retrieval requests using conditional or unconditional GET methods MAY request one or more sub-ranges of the entity, instead of the entire entity, using the Range request header (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2)

It doesn't matter if the request is for a video stream or not. I would assume that a browser (or a video player library) doesn't send a Range header for the initial request and only uses it during seeking.

robertklep
  • 198,204
  • 35
  • 394
  • 381
2

I had the same issue and solved it by @robertklep answer, thanks to him. I'm posting my answer for anyone still having the issue.

For what i understood by this https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.27

I tried this:

let range = req.headers.range
if(!range) range = 'bytes=0-'
...

And worked!

Because, range maybe undefined initially, then it updates. Even there is range its initial value is bytes=0-. As the stream goes, depending on your chunkSize, it will be something like bytes=1000001-

enter image description here

So if range is undefined, i'm setting it myself for the initial request.

A.Anvarbekov
  • 955
  • 1
  • 7
  • 21
1

You should make sure you're responding to a GET request. It could be that the browser is sending a HEAD request to get the file information. HEAD requests do not contain range headers.

Rick Doesburg
  • 673
  • 1
  • 7
  • 18