web-dev-qa-db-fra.com

En-tête HTTP

Je lisais http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 .__ et essayais de trouver un moyen de continuer le téléchargement d'un fichier.

Par exemple, supposons qu'un fichier ait une longueur de 100 octets et que je dispose de tous les 100 octets. Cependant, je ne sais pas quelle devrait être la taille de fichier attendue. Je demande donc le fichier et spécifie un en-tête Range ressemblant à ceci:

Range: bytes=100-

Est-ce une demande de plage valide?

71
dhruvbird

C'est une requête syntaxiquement valide, mais pas satisfaisante. Si vous regardez plus loin dans cette section, vous verrez:

Si un ensemble d'octets à valeur syntaxiquement valide comprend au moins une spécification d'octets dont le premier octet est inférieur à la longueur actuelle du corps de l'entité, ou au moins une spécification de suffixe-octets avec un non - longueur de suffixe zéro, l'ensemble d'octets est satisfaisable. Sinon, l'ensemble d'octets est insatisfiable. Si l'ensemble d'octets-plage n'est pas satisfaisante, le serveur DEVRAIT renvoyer une réponse avec un statut de 416 (plage requise non satisfaisante) . Sinon, le serveur DEVRAIT retourner une réponse avec un statut de 206 (contenu partiel) contenant les plages satisfaisables du corps de l'entité.

Je pense donc que dans votre exemple, le serveur devrait renvoyer un 416, car ce n'est pas une plage d'octets valide pour ce fichier.

50
Marc Novakowski

Comme Wrikken suggéré, c'est une demande valide. Il est également courant que le client demande un support ou reprenne un téléchargement. 

Un client testera souvent pour voir si le serveur gère les demandes à distance autres que la simple recherche d'une réponse Accept-Ranges. Chrome toujours envoie un Range: bytes=0- avec sa première demande GET pour une vidéo; c'est donc quelque chose que vous ne pouvez pas rejeter.

Lorsqu'un client inclut Range: dans sa demande, même s'il est mal formé, il attend une réponse de contenu partiel (206). Lorsque vous effectuez une recherche avancée lors de la lecture d'une vidéo HTML5, le navigateur ne demande que le point de départ. Par exemple:

Range: bytes=3744-

Ainsi, pour que le client puisse lire la vidéo correctement, votre serveur doit pouvoir gérer ces demandes de plage incomplètes. 

Vous pouvez gérer le type de "plage" que vous avez spécifié dans votre question de deux manières:

Tout d'abord, vous pouvez répondre avec le point de départ demandé indiqué dans la réponse, puis la longueur totale du fichier moins un (la plage d'octets demandée est indexée à zéro). Par exemple:

Demande:

GET /BigBuckBunny_320x180.mp4 
Range: bytes=100-

Réponse:

206 Partial Content
Content-Type: video/mp4
Content-Length: 64656927
Accept-Ranges: bytes
Content-Range: bytes 100-64656926/64656927

Deuxièmement, vous pouvez répondre avec le point de départ indiqué dans la demande et une longueur de fichier ouverte (taille). Ceci est pour les webcasts ou autres médias dont la longueur totale est inconnue. Par exemple: 

Demande:

GET /BigBuckBunny_320x180.mp4
Range: bytes=100-

Réponse:

206 Partial Content
Content-Type: video/mp4
Content-Length: 64656927
Accept-Ranges: bytes
Content-Range: bytes 100-64656926/*

Conseils:

Vous devez toujours répondre avec la longueur du contenu incluse dans la plage. Si la plage est complète, avec le début à la fin, la longueur du contenu est simplement la différence:

Demande: Plage: octets = 500-1000

Réponse: Contenu-Range: octets 500-1000/123456

Rappelez-vous que la plage est indexée à zéro, donc Range: bytes=0-999 demande en réalité 1000 octets, et non 999, donc répondez avec quelque chose comme:

Content-Length: 1000
Content-Range: bytes 0-999/123456

Ou:

Content-Length: 1000
Content-Range: bytes 0-999/*

Toutefois, évitez si possible cette dernière méthode, car certains lecteurs multimédias tentent de déterminer la durée à partir de la taille du fichier. Si votre demande concerne du contenu multimédia, ce qui est mon intuition, vous devez alors inclure sa durée dans la réponse. Ceci est fait avec le format suivant:

X-Content-Duration: 63.23 

Ce doit être un point flottant. Contrairement à Content-Length, cette valeur ne doit pas nécessairement être précise. Il est utilisé pour aider le joueur à rechercher autour de la vidéo. Si vous diffusez une diffusion Web et n’avez qu’une idée générale de sa durée, il est préférable d’inclure votre durée estimée plutôt que de l’ignorer complètement. Ainsi, pour une diffusion Web de deux heures, vous pouvez inclure quelque chose comme:

X-Content-Duration: 7200.00 

Avec certains types de média, tels que webm, vous devez également inclure le type de contenu, tel que:

Content-Type: video/webm 

Tous ces éléments sont nécessaires au bon fonctionnement du support, en particulier en HTML5. Si vous ne donnez pas de durée, le joueur peut essayer de déterminer la durée (pour permettre la recherche) à partir de la taille de son fichier, mais cela ne sera pas précis. C'est très bien, et nécessaire pour les diffusions Web ou la diffusion en direct, mais pas idéal pour la lecture de fichiers vidéo. Vous pouvez extraire la durée à l'aide d'un logiciel tel que FFMPEG et l'enregistrer dans une base de données ou même le nom du fichier.

X-Content-Duration est en train d'être supprimé en faveur de Content-Duration, donc je l'inclurais aussi. Une réponse de base à une demande "0-" comprendrait au moins les éléments suivants:

HTTP/1.1 206 Partial Content
Date: Sun, 08 May 2013 06:37:54 GMT
Server: Apache/2.0.52 (Red Hat)
Accept-Ranges: bytes
Content-Length: 3980
Content-Range: bytes 0-3979/3980
Content-Type: video/webm
X-Content-Duration: 2054.53
Content-Duration: 2054.53

Un dernier point: Chrome lance toujours sa première requête vidéo avec les éléments suivants:

Range: bytes=0-

Certains serveurs envoient une réponse 200 régulière sous forme de réponse, ce qu’il accepte (mais avec des options de lecture limitées), mais essayez d’envoyer un 206 à la place pour indiquer que votre serveur gère des plages. RFC 2616 indique qu'il est acceptable d'ignorer les en-têtes de plage.

127
Victor Stoddard

Contrairement à la réponse de Mark Novakowski, qui pour une raison quelconque a été votée favorablement, oui, c’est une demande valide et satisfaisante.

En fait, le standard, comme l'a souligné Wrikken, en est un exemple. En pratique, Firefox répond à ces demandes comme prévu (avec un code 206), et c’est exactement ce que j’utilise pour implémenter le téléchargement progressif, c’est-à-dire obtenir uniquement la queue d’un fichier journal long qui croît en temps réel avec polling.

7
user3198011

Pour les personnes qui tombent sur la réponse de Victor Stoddard ci-dessus en 2019, et qui deviennent optimistes et attentifs, notez que:

a) La prise en charge de X-Content-Duration a été supprimée dans Firefox 41: https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/41#HTTP

b) Je pense que cela n'a été pris en charge dans Firefox que pour les fichiers audio .ogg et vidéo .ogv, et pour aucun autre type.

c) Je ne vois pas du tout que cela ait déjà été pris en charge dans Chrome, mais il se peut que ce soit juste un manque de recherche de ma part. Mais sa présence ou son absence semble n'avoir aucun effet d'une manière ou d'une autre pour les vidéos webm ou ogv à compter d'aujourd'hui dans Chrome 71.

d) Je ne trouve aucun endroit où "Content-Duration" remplace "X-Content-Duration", je ne pense pas que "X-Content-Duration" ait vécu assez longtemps pour qu'il y ait un nom d'en-tête de successeur.

Je pense que cela signifie que, dès aujourd'hui, si vous souhaitez desservir des conteneurs Webm ou ogv contenant des flux ne connaissant pas leur durée (par exemple, la sortie d'un tube ffpeg) vers Chrome ou FF, et que vous voulez qu'ils soient scrubbable un élément vidéo HTML 5, vous n'avez probablement pas de chance. Firefox 64.0 essaie de rendre ces tâches effaçables, que vous serviez ou non via des requêtes d'intervalle, mais il devient confus et génère une roue qui tourne jusqu'à ce que le flux soit complètement téléchargé si vous cherchez plusieurs fois plus qu'il ne semble approprié. Chrome n'essaye même pas, il ne fait que passer à côté et ne vous laissera pas frotter du tout tant que tout le flux n'est pas fini en jouant.

0
Chris McDonough