FAQ
I need to perform some non-destructive operations against the body of an
outgoing http.Request before it is sent via http client. Each operation
(e.g. a hash, a word check, etc.) goes through all the byes of the body to
perform its duty. The request is created with http.NewRequest and passed
to me so I don't have access to the body before the request is created.

The concern I have is that I haven't figured out an efficient way to do
multiple, independent operations over the body contents without lots of
copying. Request.Body is a ReadCloser which doesn't have a Seeker
interface so I'm having to do something like:

cached, err := ioutil.ReadAll(req.Body)
// Replace the body with something that has the read position reset to
beginning
req.Body = ioutil.NopCloser(bytes.NewBuffer(cachedBody))
r1 := doOperation1(cached)
r2: = doOperation2(cached)

I think that most of the time in my case the body argument to NewRequest
would be from strings.NewReader() or bytes.NewReader, both of which have a
Seeker interface so I've been trying to get that interface from the
req.Body but haven't been able to. If I could get the Seeker interface (for
bodies that actually implement it of course), I wouldn't have the extra
memory copy. It may not be possible but I'm hoping someone has some
ideas. The following illustrates type of thing I would like to accomplish:

package main

import (
     "crypto/sha256"
     "fmt"
     "io"
     "net/http"
     "strings"
)

func main() {
     // Somebody, somewhere makes a new request
     requestBody := strings.NewReader("BlahBlah")
     req, err := http.NewRequest("POST", "https://www.blah.blah/incoming",
requestBody)
     if err != nil {
         return // punt for this example
     }
     analyzeRequest(req)
}

func analyzeRequest(req *http.Request) {
     sk, ok := req.Body.(io.Seeker)
     if !ok {
         fmt.Println("Can't type assert body to io.Seeker")
     } else {
         // Example to calc hash and reset read position
         hasher := sha256.New()
         io.Copy(hasher, req.Body)
         // Reset the body read point efficiently
         _, err := sk.Seek(0, 0)
         fmt.Println("Hash of body is: %x", err, hasher.Sum(nil))
     }
}

Of course, this prints out "Can't type assert body...". I noticed in the
source for NewRequest they do a type switch on the body argument but they
wrap the body argument in an ioutil.NopCloser for storage in the Body
field, which prevents my type assertion from working methinks. Any ideas
on how to accomplish this without creating an extra copy of the body?

Thanks

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedMay 18, '14 at 4:26a
activeMay 18, '14 at 4:26a
posts1
users1
websitegolang.org

1 user in discussion

Davidmac66: 1 post

People

Translate

site design / logo © 2021 Grokbase