Partitionnez l'envoi ou la réception de vos fichiers volumineux grâce aux requêtes HTTP Range

Jérémy 🤘
Jérémy 🤘

HTTP range permet d'envoyer ou recevoir une partie d'une portion d'un message HTTP. Par exemple, si vous avez un fichier de 50Go à envoyer, vous allez pouvoir "spliter" votre fichier en petits morceaux et vous pourrez bénéficier des fonctions pause et de reprise.

Détecter si le serveur accepte ou non les requêtes partielles

Pour savoir si le serveur accepte ou non ce type de requête, il vous suffit de regarder les headers qui vous sont retournés.

Copier
curl -I http://i.imgur.com/z4d4kWk.jpg
curl -I http://i.imgur.com/z4d4kWk.jpg
Copier
HTTP/1.1 200 OK
...
Accept-Ranges: bytes
Content-Length: 146515
HTTP/1.1 200 OK
...
Accept-Ranges: bytes
Content-Length: 146515

Dans cette réponse, il est indiqué Accept-Ranges: bytes. Cela veut dire qu'il accepte ce type de requête. L'information Content-Length vous indique la taille du fichier. Ici environ 150 Ko.

Si vous ne voyez pas la ligne Accept-Ranges ou si celle-ci indique none ou null, c'est que le serveur ne propose pas ce type de requêtes.

Demander une certaine plage au serveur

Si le serveur supporte le header Range, vous pouvez demander au serveur de vous envoyer le fichier avec des blocs d'une certaine taille.

Plage simple

Avec l'option -H vous allez pouvoir ajouter une ligne aux headers existants. Ici on demande les 1024 premiers octets.

Copier
curl http://i.imgur.com/z4d4kWk.jpg -i -H "Range: bytes=0-1023"
curl http://i.imgur.com/z4d4kWk.jpg -i -H "Range: bytes=0-1023"

Le serveur retourne un status 206 Partial Content ce qui nous indique bien que le contenu est en plusieurs morceaux.

Copier
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/146515
Content-Length: 1024
...
(binary content)
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/146515
Content-Length: 1024
...
(binary content)

Content-Range nous montre bien qu'il ne nous envoi que les 1 024 premiers octets sur 146 515 octets du fichier complet. Quant à Content-Length il nous dit que la taille est bien de 1 024 octets.

Plage multiple

Il est aussi possible de demander plusieurs plages d'un coup en les séparant par des virgules.

Copier
curl http://www.example.com -i -H "Range: bytes=0-50, 100-150"
curl http://www.example.com -i -H "Range: bytes=0-50, 100-150"

Le serveur nous répond là aussi avec un status 206 Partial Content mais aussi avec un Content-Type: multipart/byteranges; boundary=3d6b6a416f9b5 ce qui veut dire qu'il y aura plusieurs parties dans la réponse et qu'elles seront séparées par 3d6b6a416f9b5. Et dans chacune de ces parties nous retrouvons les champs Content-Type et Content-Range qui nous donne les informations de taille et de type de contenu qui est retourné dans chacun des blocs.

Copier
HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=3d6b6a416f9b5
Content-Length: 282

--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 0-50/1270

<!doctype html>
<html>
<head>
    <title>Example Do
--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 100-150/1270

eta http-equiv="Content-type" content="text/html; c
--3d6b6a416f9b5--
HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=3d6b6a416f9b5
Content-Length: 282

--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 0-50/1270

<!doctype html>
<html>
<head>
    <title>Example Do
--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 100-150/1270

eta http-equiv="Content-type" content="text/html; c
--3d6b6a416f9b5--

Types de status

Il existe 3 status qui sont les plus fréquents lors de l'utilisation des requêtes Range.

206 Partial Content

Le serveur a répondu correctement à votre demande d'une requête Range.

416 Requested Range Not Satisfiable

La plage que vous demandez est hors limites. Les valeurs se chevauchent ou alors vous demandez une plage qui est au-delà du poids du fichier.

200 OK

Le serveur ne supporte pas les requêtes Range et il vous envoie le fichier en entier. Il n'est donc pas possible d'avoir les fonctions pause et reprise.

Source

MDN web docs (en anglais)