preface

When downloading a movie, I often wonder why, after stopping the download, I click Start and continue downloading where I left off. Or when watching an online movie, why can you just hold down the playbar and drag to see the desired clip?

The HTTP range request resolves this confusion.

Multithreading, breakpoint continuation, random on demand, etc

1, the client clear task: where to start the download

  • Whether some files have been downloaded locally: Are the downloaded files changed on the server?
  • Use several threads to download concurrently

Download the specified part of the file. 3. Assemble the file into a unified file after downloading

HTTP Range specification

It is detailed in RFC7233. 1. The server is allowed to send only part of the response package to the client based on the client’s request, and the client automatically combines multiple fragments into a complete and larger package.

  • Support breakpoint continuation
  • Support multi-threaded download
  • Supports real-time dragging of video player

2. The server uses the accept-range header to indicate whether Range requests are supported

  • Accept-Ranges = acceptable-ranges
  • For example, accept-ranges: bytes: supports this command. Accept-ranges: None: not supported

Range Unit of the request Range

For the unit of bytes, for example, set the response body length to 10000

  • First 500 bytes: bytes=0-499 // start from 0
  • Second 500 bytes: bytes=500-999 bytes=500-600, 601-999 bytes=500-700, 601-999
  • The last 500 bytes=-500 bytes=9500-
  • Only the first and last bytes are required: bytes=0-0, -1

Pass the request Range through the Range header, for example, Range: bytes=0-499

test

Here are some small examples to test. A simple server is built with Node, and the number returned is a 22-byte response body

'Hello World 0123456789';
Copy the code

Curl curl curl curl curl curl curl curl curl curl curl curl

The -h parameter adds the HTTP request header. Range: bytes=0-5 The return is Hello (plus space), which is six bytes.

Now to get the 21st byte and subsequent bytes, use 20- :

The return is 89

Range conditional request

  • If the client has received part of the Range response and wants to get the other part of the response without it being expired, it is often used in conjunction with if-unmodified-since or if-match headers
  • If-range = entity-tag/http-date The value can be Etag or last-Modified

test

Let’s test the Range condition request using etag

First get the 0-5 byte segment

I is then used to see the value of the Etag generated by the server when Hello is generated

Next, put this value into if-match to get the 6-10 byte segment: World

If the Etag changes, let’s see what happens, change the last 0 to 1. Okay

Return 412 Feed Failed

conclusion

Conditional requests can be used to determine whether the server side resources have changed between downloads. If there is a change, you know from the 412 response that the resource has changed.

Server response

If only the body of the part is retrieved, the response code returned by the server is 206 instead of 200. 206 Partial Content

  • Content-range header: Displays the position of the current fragment response body in the complete package

  • Content-Range = byte-content-range / other-content-range { btye-content-range = bytes-unit SP (byte-range-resp / Unsatisfied-range) byte-range-resp = byte-range ‘/’ (complete-length/”) complete-length = 1DIGIT Bytr-range = first-byte-pos “-” last-byte-pos} bytr-range = first-byte-pos “-” last-byte-pos}

  • For example, 1. Content-range: bytes 42-1233/1234 2. Content-range: bytes 42-1233/*

test

Use an example of video playback to see how 206 responds.

416 Range Not Statisfiable

  • The request Range does not meet the size of the actual resource. The complete-Length field in content-range shows the length of the complete response, for example, content-range: bytes */1234

test

If the fetch range is larger than the actual resource size, say 30-40. Back to 416

200 OK

  • When the server does not support a Range request, the complete response package body is returned with 200

Multiple ranges with multiparts

  • Request: Range: bytes=0-50, 100-150
  • Response: Content-type: multipart/byteranges; boundary=…

test

Get 5-10, 10-15 fragments.

conclusion

1. The client passes the request scope through the Range header

2. The server returns the accept-range header to indicate whether the Range request is supported.

3. If a client obtains part of a Range response and wants to obtain other parts of the response without the part of the response being expired, it can use the Etag or last-Modified value in the if-range header.

4. The server returns a 206 response code, where the Content-range header shows the position of the current fragment response body in the complete package

Range: bytes=0-50, 100-150… Range: bytes=0-50, 100-150… (Separated by commas) Response headers Content-Type: multipart/ Byteranges; boundary=…

series

  • Http series: http1.1 protocol base
  • Http series: content negotiation and resource representation

For more articles, please go to Github, if you like, please click star, which is also a kind of encouragement to the author