There's not a nice way to serialize the http.Request
structure itself (see notes below), but you can serialize the request back into HTTP/1.1 wire format (and deserialize too). This can be done using Request.Write
and http.ReadRequest
:
func captureRequestData(req *http.Request) error {
var b = &bytes.Buffer{} // holds serialized representation
var tmp *http.Request
var err error
if err = req.Write(b); err != nil { // serialize request to HTTP/1.1 wire format
return err
}
r := bufio.NewReader(b)
if tmp, err = http.ReadRequest(r); err != nil { // deserialize request
return err
}
*req = *tmp // replace original request structure
return nil
}
Persistence of the serialized buffer is just a matter of saving a copy of b
. You might prefer to persist the string
representation, which involves some additional conversions:
s := b.String() // persist this
r := bufio.NewReader(strings.NewReader(s))
There are a couple of reasons, at least, why you can't just use json.Marshal()
for this:
The public fields of Request
include functions, which Marshall does not accept:
json: unsupported type: func() (io.ReadCloser, error)
Request
also contains a private field ctx
which thwarts any generic attempts at deserialization:
ctx is either the client or server context. It should only
be modified via copying the whole Request using WithContext.
It is unexported to prevent people from using Context wrong
and mutating the contexts held by callers of the same request.