La lecture du corps de http.Demande sans modification de la demande de l'état?
J'ai un type de mise en œuvre de la http.Handler
interface où, dans son ServeHTTP
méthode, les requêtes HTTP entrantes sont inspectés, certaines mesures sont prises, puis les demandes sont transmises à un serveur proxy inverse gestionnaire (httputil.NewSingleHostReverseProxy
).
Cela fonctionne très bien, aussi longtemps que je suis seule inspection de la demande de base des propriétés, telles que l'URL ou les en-têtes.
Quand je veux inspecter le corps de la réception d'une requête POST, par exemple en appelant req.ParseForm()
et puis, à l'aide de la req.Form
bien, je tombe sur une erreur une fois que la demande est transmise sur le reverse proxy:
http: proxy error: http: Request.ContentLength=687 with Body length 0
J'imagine que ce qui se passe parce qu'en regardant le corps de la requête HTTP causes de la req.Body.Reader
flux drainés, ce qui signifie qu'il ne peut pas être lu à nouveau par le proxy handler.
J'ai été jouer avec des choses comme io.Copy()
et bufio.Peek()
, mais je ne suis pas vraiment d'aller n'importe où.
Est-il un moyen de jeter un regard sur le corps de requête HTTP (et l'utilisation de l'intégré dans l'analyse de req.ParseForm
etc.), tout en laissant l'original de la demande d'objet dans son état d'origine, de sorte qu'il peut être transmis à la reverse proxy?
- Avez-vous essayé de remplacer le
Body
avec un seekable lecteur commebytes.Reader
? Vous pouvez définirBody
à chaque valeur qui implémenteReadCloser
. - Non testé (mais vaut la peine d'essayer): Faire une copie de la Demande au besoin, c'est à dire tous, mais pas le Corps et l' .*Forme. Ensuite, utilisez io.TeeReader cloner Demande.Corps, de l'envelopper dans un NopCloser et des trucs dans le propriétédeepcopy de la demande. Passer la copie en profondeur pour le proxy inverse.
Vous devez vous connecter pour publier un commentaire.
Essayer de lecture dans une mémoire tampon, puis à l'aide de la mémoire tampon pour le retour de deux nouveaux lecteurs, pour vous, et un pour la suite des consommateurs à utiliser. Par exemple, imaginons que nous voulons modifier le code suivant:
Nous pourrions faire:
Noter que
*bytes.Buffer
ne dispose pas d'unClose() error
méthode, afin de ne pas mettre en œuvre laio.ReadCloser
interface. Ainsi, nous avons pour envelopper notre*bytes.Buffer
valeurs dans les appels àioutil.NopCloser
.io.ReadCloser
à partir d'un tampon à l'aide de laio.NopCloser
fonction, par exempleio.NopCloser(buf)
. Voir golang.org/src/pkg/io/ioutil/ioutil.go?s=3623:3664#L111drainBody
dans golang.org/src/net/http/httputil/dump.go#L26 propose une solution similaire, mais la prise dehttp.NoBody
en compte.J'ai utilisé une approche différente de cette plus récemment. Il y a un
GetBody
méthode, par le biais de laquelle vous pouvez obtenir une nouvelle copie de la demande de corps, de sorte qu'au lieu de faire:Vous pourriez faire au lieu de:
Cela vous permet d'inspecter le corps de la requête, tout en ayant encore autour de poursuivre le traitement plus tard
GetBody()
est utilisé uniquement pour les demandes des clients. Pour les demandes de serveur qu'il est utilisé.