web-dev-qa-db-fra.com

Réponse HTTP en plusieurs parties

L'objectif est qu'un serveur Node.js/ hapi API réponde à la demande d'un navigateur AJAX avec deux choses:

  • Un fichier multimédia (par exemple une image)
  • Un objet JSON avec des métadonnées sur le fichier

Ce ne sont que deux éléments distincts car les données binaires ne peuvent pas être facilement stockées dans JSON. Sinon, ce serait une seule ressource. Néanmoins, il est préférable de les envoyer en une seule réponse.

Nous les téléchargeons en une seule demande avec multipart/form-data. Dans ce cas, les navigateurs fournissent un mécanisme intégré pour sérialiser le corps et la plupart des frameworks côté serveur savent comment l'analyser. Mais comment faire la même chose pour une réponse, dans la direction opposée? À savoir, comment un serveur doit-il sérialiser le corps pour le transmettre à un client?

D'après ce que je peux dire, multipart/mixed pourrait être un type de contenu utile. Mais on en parle très peu. La plupart des gens semblent avoir recours à deux itinéraires GET distincts, un pour chaque morceau. Je n'aime pas cela parce que cela vous ouvre, entre autres, aux conditions de course. Qu'est-ce que je rate?

Voir aussi ma question dans hapijs/discuter # 56 .

8
Seth Holladay

Vous pouvez servir la réponse sous la forme multipart/form-data Et utiliser Response.formData() pour lire la réponse sur le client

fetch("/path/to/server", {method:"POST", body:formData})
.then(response => response.formData())
.then(fd => {
  for (let [key, prop] of fd) {
    console.log(key, prop)
  }
})
let fd = new FormData();
fd.append("json", JSON.stringify({
  file: "image"
}));
fetch("data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==")
  .then(response => response.blob())
  .then(blob => {
    fd.append("file", blob);
    new Response(fd)
      .formData()
      .then(formData => {
        for (let [key, data] of formData) {
          console.log(key, data)
        }
      })
  })
5
guest271314

Si vous optez pour un format en plusieurs parties, je ne pense pas qu'il y ait quelque chose d'intrinsèquement mauvais à utiliser exactement le même format à la fois lors du téléchargement (POST/PUT) et de la récupération (GET).

Je pense qu'il y a certainement une élégance à utiliser le même format sur fil dans les deux sens lorsque vous travaillez avec HTTP.

Cependant, si vous souhaitez envoyer des données de formulaire pendant PUT/POST et JSON en utilisant GET, je commencerais à me demander si c'est la bonne chose à faire.

multipart devient ennuyeux pour les clients s'ils veulent simplement afficher l'image. Avez-vous envisagé d'utiliser simplement différents points de terminaison; un pour l'image et un pour ses métadonnées? Quelle raison avez-vous de vouloir les combiner en une seule ressource?

Vous pouvez également essayer d'intégrer les informations dans l'image. JPEG, par exemple, permet d'ajouter des données personnalisées à l'aide d'EXIF. Au moins, vous conservez la possibilité d'ouvrir simplement l'image directement.

Cependant, je conclurai en disant que multipart/mixed est approprié si vous souhaitez simplement incorporer une image + un objet json, mais gardez à l'esprit:

  1. C'est probablement un peu gênant pour la consommation
  2. C'est aussi un peu inhabituel
  3. Je suis assez sûr que le codage en plusieurs parties vous obligera à coder votre image dans un codage 7 bits, ce qui entraînera de manière inhérente la taille de la demande à exploser un peu.
2
Evert