Passer au contenu principal


Mise à jour

Chrome 85 a une implémentation expérimentale des flux de requêtes, ce qui signifie que vous pouvez commencer à faire une requête avant que le corps complet ne soit disponible.

Vous pouvez l'utiliser pour :

  • Faites chauffer le serveur. En d'autres termes, vous pouvez démarrer la demande une fois que l'utilisateur se concentre sur un champ de saisie de texte et supprime tous les en-têtes, puis attendez que l'utilisateur appuie sur "soumettre" avant d'envoyer les données saisies.
  • Envoyez progressivement des données générées par le client telles que des données audio, vidéo ou d'entrée.
  • Recrée les sockets Web sur HTTP.

Mais comme il s'agit d'une fonction de plate-forme Web de bas niveau, ne vous limitez pas à moi idées. Vous pouvez peut-être penser à un cas d'utilisation beaucoup plus intéressant pour le streaming de requêtes.

Tester les flux de requêtes

Activer le support lors de la phase de preuve d'origine

Les flux de requêtes de récupération sont disponibles dans un test d'origine à partir de Chrome 85. Le test d'origine devrait se terminer dans Chrome 87.

Les tests d'origine vous permettent de tester de nouvelles fonctionnalités et de fournir des commentaires sur leur convivialité, leur caractère pratique et leur efficacité à la communauté des normes Web. Pour plus d'informations, consultez le Guide de test d'origine pour les développeurs Web. Pour vous inscrire à cette preuve d'origine ou à toute autre preuve d'origine, visitez le page d'inscription.

Inscrivez-vous pour obtenir une preuve d'origine

  1. Demander un jeton par votre origine.
  2. Ajoutez le jeton à vos pages. Il y a deux façons de le faire:
    • Ajouter un origine-procès balise à l'en-tête de chaque page. Par exemple, cela pourrait ressembler à ceci:
    • Si vous pouvez configurer votre serveur, vous pouvez également ajouter le jeton à l'aide d'un Essai d'origine En-tête HTTP. L'en-tête de réponse qui en résulte doit ressembler à ceci:
      Essai d'origine: TOKEN_GOES_HERE

Activation via chrome: // flags

Testez les flux de requêtes dans Chrome 85 en activant un indicateur expérimental :
activer les fonctionnalités expérimentales de la plate-forme Web.

Manifestation

Cela montre comment vous pouvez transmettre des données de l'utilisateur au serveur et envoyer des données qui peuvent être traitées en temps réel.

Ouais, d'accord, ce n'est pas l'exemple le plus imaginatif, je voulais juste que ce soit simple, d'accord ?

Quoi qu'il en soit, comment cela fonctionne-t-il ?

Précédemment dans les aventures passionnantes de fetch streams

Répondre Les flux sont disponibles dans tous les navigateurs modernes depuis un certain temps. Ils vous permettent d'accéder à des parties d'une réponse à mesure qu'elles arrivent du serveur :

réponse const = attendre récupérer ( url ) ;
const lecteur = réponse . corps . getReader ( ) ;

tandis que ( vrai ) {
const { valeur , fait } = attendre le lecteur . lire ( ) ;
si ( fait ) pause ;
consoler . log ( 'Reçu' , valeur ) ;
}

consoler . log ( 'Réponse entièrement reçue' ) ;

Chaque valeur c'est un Uint8Array d'octets. Le nombre de tableaux que vous obtenez et la taille des tableaux dépendent de la vitesse du réseau. Si vous disposez d'une connexion rapide, vous obtiendrez moins de "morceaux" de données plus volumineuses. Si vous avez une connexion lente, vous obtiendrez des morceaux plus petits.

Si vous souhaitez convertir les octets en texte, vous pouvez utiliser
TextDecoderou la transmission de transformation la plus récente si votre les navigateurs cibles le supportent:

réponse const = attendre récupérer ( url ) ;
const lecteur = réponse . le maillot de corps
. pipeThrough ( nouveau TextDecoderStream ( ) )
. getReader ( ) ;

TextDecoderStream est un courant de transformation qui rattrape tous ceux Uint8Array
fragments et les transforme en chaînes.

Les flux sont formidables car vous pouvez commencer à agir sur les données au fur et à mesure qu'elles arrivent. Par exemple, si vous recevez une liste de 100 "résultats", vous pouvez afficher le premier résultat dès sa réception, au lieu d'attendre les 100.

Quoi qu'il en soit, ce sont les flux de réponse, la chose nouvelle et passionnante dont je voulais parler est le flux de demande.

Organismes de demande de transmission

Les requêtes peuvent avoir des corps :

attendre récupérer ( url , {
méthode : 'POST' ,
body : requestBody ,
} ) ;

Auparavant, vous aviez besoin de tout le corps prêt à l'emploi avant de pouvoir lancer la demande, mais maintenant, dans Chrome 85, vous pouvez fournir le vôtre ReadableStream de données :

fonction attendre ( millisecondes ) {
return new Promise ( ( résolvez ) => setTimeout ( résolvez , millisecondes ) ) ) ;
}

flux const = nouveau flux lisible ( {
démarrage asynchrone ( contrôleur ) {
attendre attendre ( 1000 ) ; _
contrôleur . mettre en file d'attente ( 'Ceci' ) ;
attendre attendre ( 1000 ) ; _
contrôleur . mettre en file d'attente ( 'est' ) ;
attendre attendre ( 1000 ) ; _
contrôleur . mettre en file d'attente ( 'a' ) ;
attendre attendre ( 1000 ) ; _
contrôleur . mettre en file d'attente ( 'lent' ) ;
attendre attendre ( 1000 ) ; _
contrôleur . mettre en file d'attente ( 'demande.' ) ;
contrôleur . fermer ( ) ;
} ,
} ) . pipeThrough ( new TextEncoderStream ( ) ) ;

récupérer ( url , {
méthode : 'POST' ,
en-têtes : { 'Content-Type' : 'text/plain' } ,
corps : flux ,
} ) ;

Ce qui précède enverra "Ceci est une requête lente" au serveur, un mot à la fois, avec une pause d'une seconde entre chaque mot.

Chaque partie du corps d'une demande doit être un Uint8Array d'octets, donc j'utilise
pipeThrough(nouveau TextEncoderStream()) faire la conversion pour moi.

flux enregistrables

Parfois, il est plus facile de travailler avec des flux lorsque vous avez un WritableStream. Vous pouvez le faire en utilisant un flux "d'identité", qui est une paire lisible/inscriptible qui prend tout ce qui est passé à votre extrémité d'écriture et l'envoie à l'extrémité de lecture. Vous pouvez en créer un en créant un TransformStream sans aucun argument :

const { lisible , inscriptible } = new TransformStream ( ) ;

const responsePromise = chercher ( url , {
méthode : 'POST' ,
corps : lisible ,
} ) ;

Désormais, tout ce que vous envoyez au flux d'écriture fera partie de la requête. Cela vous permet de composer des flux ensemble. Par exemple, voici un exemple idiot où les données sont extraites d'une URL, compressées et envoyées à une autre URL :


réponse const = attendre la récupération ( url1 ) ;
const { lisible , inscriptible } = new TransformStream ( ) ;


réponse . le maillot de corps
. pipeThrough ( new CompressionStream ( 'gzip' ) )
. pipeTo ( inscriptible ) ;


attendre récupérer ( url2 , {
méthode : 'POST' ,
corps : lisible ,
} ) ;

L'exemple ci-dessus utilise flux de compression pour compresser des données arbitraires à l'aide de gzip.

Détection des fonctionnalités

Si vous fournissez un objet corps que le navigateur ne gère pas spécifiquement, il appellera toString() dans l'objet et utiliser le résultat comme corps. Si le navigateur ne prend pas en charge les flux de requêtes, cela signifie que le corps de la requête devient
"[objet ReadableStream]" – probablement pas ce que vous voulez envoyer au serveur. Pour éviter cela, utilisez la détection de fonctionnalités :

const prend en chargeRequestStreams = ! nouvelleRequête ( ' ' , {
corps : nouveau ReadableStream ( ) ,
méthode : 'POST' ,
} ) . en-têtes . a ( 'Content-Type' ) ;

si ( supportsRequestStreams ) {
} sinon {
}

Cela fonctionne parce que le navigateur ajoute un Type de contenu en-tête de
text/plain;charset=UTF-8 à la requête si le corps est du texte. Le navigateur ne traite le corps comme du texte que si non prend en charge les flux de demandes, sinon il n'ajoutera pas de Type de contenu en-tête du tout.

restriction

Les requêtes de streaming sont un nouveau pouvoir sur le Web, elles s'accompagnent donc de quelques restrictions :

redirections restreintes

Certaines formes de redirection HTTP nécessitent que le navigateur renvoie le corps de la requête à une autre URL. Pour prendre en charge cela, le navigateur devrait mettre en mémoire tampon le contenu du flux, qui remplace point, donc il ne le fait pas.

Inversement, si la requête a un corps de flux et que la réponse est une redirection HTTP autre que 303, la récupération sera rejetée et la redirection non être suivi.

Les redirections 303 sont autorisées, car elles modifient explicitement la méthode pour OBTENIR et supprimez le corps de la requête.

HTTP/2 uniquement par défaut

Par défaut, la récupération sera refusée si la connexion n'est pas HTTP/2. Si vous souhaitez utiliser des requêtes de streaming sur HTTP/1.1, vous devez vous inscrire :

attendre récupérer ( url , {
méthode : 'POST' ,
corps : flux ,
allowHTTP1ForStreamingUpload : vrai ,
} ) ;

Mise en garde:
allowHTTP1ForStreamingUpload il n'est pas standard et ne sera utilisé que dans le cadre de la mise en œuvre expérimentale de Chrome.

Selon les règles HTTP/1.1, les corps de requête et de réponse doivent envoyer un
Contenu-Longueur l'en-tête, afin que l'autre côté sache combien de données il recevra, ou modifier le format du message à utiliser codage fragmenté. Avec l'encodage fragmenté, le corps est divisé en parties, chacune avec sa propre longueur de contenu.

L'encodage Chunky est assez courant lorsqu'il s'agit de HTTP/1.1 réponses, mais très rare quand il s'agit de demandes. Pour cette raison, Chrome est un peu préoccupé par la compatibilité, il est donc activé pour le moment.

Ce n'est pas un problème pour HTTP/2, puisque les données HTTP/2 sont toujours « fragmentées », même si elles appellent des fragments
cadres. Le codage Chunky n'a pas été introduit avant HTTP/1.1, donc les requêtes avec des corps de flux échoueront toujours sur les connexions HTTP/1.

Selon le déroulement de ce test, la spécification limitera les réponses en continu à HTTP/2 ou l'autorisera toujours à la fois pour HTTP/1.1 et HTTP/2.

Pas de communication duplex

Une fonctionnalité peu connue de HTTP (bien que le fait qu'il s'agisse d'un comportement standard dépend de la personne à qui vous demandez) est que vous pouvez commencer à recevoir la réponse tout en envoyant la requête. Cependant, il est si peu connu qu'il n'est pas bien pris en charge par les serveurs et, bien, les navigateurs.

Dans l'implémentation actuelle de Chrome, vous n'obtiendrez la réponse qu'après l'envoi complet du corps. Dans l'exemple suivant réponsePromise il ne sera pas résolu tant que le flux lisible n'aura pas été fermé. Tout ce que le serveur envoie avant ce point sera mis en mémoire tampon.

const responsePromise = chercher ( url , {
méthode : 'POST' ,
corps : readableStream ,
} ) ;

La deuxième meilleure option pour une communication en duplex intégral consiste à effectuer une recherche avec une demande de diffusion, puis à effectuer une nouvelle recherche pour recevoir la réponse de diffusion. Le serveur aura besoin d'un moyen d'associer ces deux requêtes, comme un ID dans l'URL. C'est ainsi que fonctionne la démo.

Problèmes potentiels

Ouais, donc... c'est une nouvelle fonctionnalité, et elle n'est pas beaucoup utilisée sur Internet ces jours-ci. Voici quelques problèmes à prendre en compte :

Incompatibilité côté serveur

Certains serveurs d'applications ne prennent pas en charge les demandes de diffusion en continu, mais attendent que la demande complète soit reçue avant de vous permettre de regarder quoi que ce soit, ce qui va à l'encontre du but. Utilisez plutôt un serveur d'applications prenant en charge le streaming, tel que
NodeJSName.

Mais vous n'êtes pas encore tiré d'affaire ! Le serveur d'application, tel que NodeJS, est généralement derrière un autre serveur, souvent appelé "serveur frontal", qui lui-même peut être derrière un CDN. Si l'un d'eux décide de mettre la requête en mémoire tampon avant de la transmettre au serveur suivant de la chaîne, il perdra le bénéfice de la diffusion en continu des requêtes.

De plus, si vous utilisez HTTP/1.1, l'un des serveurs peut ne pas être prêt pour l'encodage fragmenté et peut échouer avec une erreur. Mais bon, vous pouvez au moins essayer cela et essayer de changer de serveur si nécessaire.

... longue respiration ...

Incompatibilité indépendante de votre volonté

Si vous utilisez HTTPS, vous n'avez pas à vous soucier des proxys entre vous et l'utilisateur, mais l'utilisateur peut exécuter un proxy sur sa machine. Certains logiciels de protection Internet font cela pour vous permettre de surveiller tout ce qui se passe entre le navigateur et le réseau.

Il peut y avoir des cas où ce logiciel met en mémoire tampon les corps de requête, ou dans le cas de HTTP/1.1, ne vous attendez pas à un encodage volumineux et il se casse d'une manière intéressante.

À l'heure actuelle, on ne sait pas à quelle fréquence, le cas échéant, cela se produira.

Si vous voulez vous prémunir contre cela, vous pouvez créer un "test de fonctionnalité" similaire à la démo ci-dessus, où vous essayez de diffuser des données sans fermer le flux. Si le serveur reçoit les données, il peut répondre via une recherche différente. Une fois que cela se produit, vous savez que le client prend en charge les demandes de streaming de bout en bout.

commentaires bienvenus

Les commentaires de la communauté sont cruciaux lors de la conception de nouvelles API, alors essayez-les et dites-nous ce que vous en pensez. Si vous trouvez des erreurs, veuillez signalez-les, mais si vous avez des commentaires généraux, veuillez les envoyer à Groupe Google blink-network-dev.

photo par Laura Lefurgey-Smith
au
Unsplash

R Marketing Numérique