title: Video seeking in Google Chrome: How to handle continuous Partial Content requests?
body: <p>This question may be a little overwhelming, but I feel close to understanding the way video seeking works in Google Chrome, but it's still very confusing to me and support is difficult to find.</p>
  
  <p>If I am not mistaken, Chrome initially sends a request header with Range <strong>bytes=0-</strong> to test if the server understands <strong>Partial Content</strong> requests, and expects the server to respond with status code <strong>206</strong>.</p>
  
  <p>I have read the following answers to get a better understanding:<br>
  <em>Need more rep to link them, their topics are:</em><br>
  <strong>can't seek html5 video or audio in chrome</strong><br>
  <strong>HTML5 video will not loop</strong><br>
  <strong>HTTP Range header</strong></p>
  
  <p>My server is powered by Node.js and I am having trouble with getting continuous range requests out of chrome during playback. When a video is requested, the server receives a bytes=0-, the server then responds with status code 206 and
  then the media player <em>breaks</em>.  </p>
  
  <p>My confusion is with with the response header, because I am not sure how to
  construct my response header and handle eventual range requests:</p>
  
  <ol>
  <li>Do I respond with a status code <em>200</em> or <em>206</em> initially?
  When I respond with <em>206</em> I only receive bytes=0-, but when I respond with
  <em>200</em> I receive bytes=0- and after that bytes=355856504-.
  If I were to subtract 355856504 of the total Content-Length of the video file, the result is 58, and bytes=0-58 seems like a valid Content-Range?
  But after those two requests, I receive no more range requests from Chrome.</li>
  </ol>
  
  <p>I am also unsure if the Content-Range in the response header should looks like "bytes=0-58" or like "bytes=0-58/355856562" for example.</p>
  
  <p>Here is the code</p>
  
  <pre><code>if(req.headers.range) console.info(req.headers.range); // prints bytes=0-
  
  const type = rc.sync(media, 0, 32); // determines mime type
  const size = fs.statSync(media)["size"]; // determines content length
  
  // String range, initially "bytes=0-" according to Chrome
  var Strange = req.headers.range;
  
  res.set({
    "Accept-Ranges": "bytes",
    "Content-Type": ft(type).mime,
    "Content-Length": size-Strange.replace(/bytes=/, "").split("-")[0],
    "Content-Range": Strange+size+"/"+size
  });
  
  //res.status(206); // one request from chrome, then breaks
  res.status(200);   // two requests from chrome, then breaks
  
  // this prints 35585604-58, whereas i expect something like 0-58
  console.log("should serve range: "+
    parseInt(Strange.replace(/bytes=/, "").split("-")[0]) +"-"+
    parseInt(size-Strange.replace(/bytes=/, "").split("-")[0])
  );
  
  // this function reads some bytes from 'media', and then streams it:
  fs.createReadStream(media, {
    start: 0,
    end: parseInt(size-Strange.replace(/bytes=/, "").split("-")[0]) // 58
  }).pipe(res);
  </code></pre>
  
  <p>Screenshots of the request and response headers when status code is 200:<br>
  <a href="http://i.stack.imgur.com/EnCzc.png" rel="nofollow">first response and request headers</a><br>
  <a href="http://i.stack.imgur.com/txqBm.png" rel="nofollow">second response and request headers</a></p>
  
  <p>Screenshot of the request and response header when status code is 206:<br>
  <em>Need more rep, to show another screenshot</em><br>
  Essentially the request is:<br>
  "Range: bytes=0-"<br>
  and the Content-Range response is:<br>
  "bytes=0-355856562/355856562"</p>