Golang lire du corps de la requête
Je suis en train d'écrire mon propre logginMiddleware. En gros, j'ai besoin de vous connecter corps de la requête et la réponse. Le problème que j'ai rencontré est que quand j'ai lu corps, il devient vide et je ne peux pas le lire deux fois.
Je comprends qu'il se passe, parce qu'il est de type ReadCloser. Est-il possible de rembobiner corps pour le début?
- Attribuer corps à une variable et l'utiliser?
- Si je fais cela, alors cette variable pointe vers le même lecteur
Vous devez vous connecter pour publier un commentaire.
Inspectant et en se moquant du corps de la requête
Lorsque vous lisez d'abord le corps, vous devez le stocker une fois que vous avez fini avec cela, vous pouvez définir un nouveau
io.ReadCloser
que le corps de la requête construite à partir des données d'origine. Alors, quand on avance dans la chaîne, le gestionnaire suivant peut lire le même corps.Une option est de lire l'ensemble du corps à l'aide de
ioutil.ReadAll()
, qui vous donne le corps comme un octet tranche.Vous pouvez utiliser
octets.NewBuffer()
pour obtenir uneio.Lecteur
à partir d'un octet tranche.La dernière pièce manquante est de faire de la
io.Reader
unio.ReadCloser
, parce quebytes.Buffer
ne dispose pas d'unClose()
méthode. Pour cela, vous pouvez utiliserioutil.NopCloser()
qui encapsule uneio.Reader
, et renvoie unio.ReadCloser
, dont ajoutéeClose()
méthode sera un no-op (ne fait rien).Notez que vous pouvez même modifier le contenu de l'octet tranche que vous utilisez pour créer le "nouveau" corps. Vous avez le plein contrôle sur elle.
Soins doivent être pris même si, comme il pourrait y avoir d'autres champs HTTP comme content-length et les sommes de contrôle qui peut devenir non valide si vous modifiez uniquement les données. Si par la suite des gestionnaires de vérifier ces, vous aussi, vous avez besoin de modifier ces trop!
Inspection /modifier le corps de la réponse
Si vous aussi vous voulez lire le corps de la réponse, alors vous devez envelopper la
http.ResponseWriter
que vous obtenez, et passer le wrapper sur la chaîne. Ce wrapper peut mettre en cache les données envoyées, que vous pouvez inspecter après, sur la volée (par la suite à des gestionnaires d'écrire).Ici est un simple
ResponseWriter
wrapper, qui met en cache les données, de sorte qu'il sera disponible après que la réparation gestionnaire retourne:Noter que
MyResponseWriter.Write()
juste écrit les données dans un tampon. Vous pouvez également choisir de l'inspecter à la volée (dans leWrite()
méthode) et écrire les données directement sur le enveloppés intégrés/ResponseWriter
. Vous pouvez même modifier les données. Vous avez le plein contrôle.Soins doivent être prises à nouveau si, par la suite les gestionnaires peuvent aussi envoyer des en-têtes de réponse HTTP liée à la réponse de données –telles que la longueur, ou sommes– qui peut également devenir invalide si vous modifiez les données de réponse.
Exemple complet
De mettre les morceaux ensemble, voici un exemple de travail:
ioutil.ReadAll
n'est pas recommandé pour corps de requête http la manipulation, en particulier pour les charges élevées des serveurs. Voir: haisum.github.io/2017/09/11/golang-ioutil-readallJe pouvais utiliser le
GetBody
de trousse de Demande.Look de ce commentaire dans le code source de demande.aller net/http:
GetBody func() (io.ReadCloser, error)
De cette façon, vous pouvez obtenir le corps demande sans rendez vide.
Exemple:
runtime error: invalid memory address or nil pointer dereference
va se passergetBody := request.GetBody copyBody, err := getBody() if err != nil { // Do something return err } http.DefaultClient.Do(request)