Re-reading http.Response.Body (or any Reader)

9,284 views
Skip to first unread message

Martin Angers

unread,
Oct 12, 2012, 8:49:42 PM10/12/12
to golan...@googlegroups.com
Hi,

It seems like any reader, and in my specific use-case, http.Response.Body, is forward-only, so that once it is read, it can't be consumed again. Since it is exposed as a Reader (ReadCloser in that particular case), Read() is obviously the only available method.

I'm writing a library that needs to read the response's body, but would still like to leave it available for the client code. Is there any way to "rewind" the pointer to the beginning so that it can be read again? Otherwise what would be a good workaround? I guess it could be ok to re-assign to the Body with a ReadCloser built from its own slice of bytes, or is that a bad idea?

Thanks,
Martin

Jesse McNelis

unread,
Oct 12, 2012, 10:42:26 PM10/12/12
to Martin Angers, golan...@googlegroups.com
On Sat, Oct 13, 2012 at 11:49 AM, Martin Angers
<martin....@gmail.com> wrote:
> I'm writing a library that needs to read the response's body, but would
> still like to leave it available for the client code. Is there any way to
> "rewind" the pointer to the beginning so that it can be read again?

There is no pointer, http.Response.Body is reading from the network.
So you can't rewind.

> Otherwise what would be a good workaround? I guess it could be ok to
> re-assign to the Body with a ReadCloser built from its own slice of bytes,
> or is that a bad idea?

If you want to buffer the data in http.Response.Body the best way is
to read it in to a buffer.
http://golang.org/pkg/bytes/#Buffer
http://golang.org/pkg/io/#Copy


--
=====================
http://jessta.id.au

Evan Shaw

unread,
Oct 12, 2012, 11:53:46 PM10/12/12
to Martin Angers, golan...@googlegroups.com
If you only have a Read method, all you can do is read. You can check
to see if the Reader implements io.ReadSeeker, but in general, it's
not possible.

However, what you can do is record the bytes somewhere as you read
them. Then read them back again. io.TeeReader works well for this.
Just use a bytes.Buffer as the writer.

- Evan

Martin Angers

unread,
Oct 13, 2012, 10:59:54 AM10/13/12
to golan...@googlegroups.com
Thanks guys, that's pretty much the conclusion I reached. I buffered the body and re-assigned the Response.Body field (using ioutil.NopCloser()) so that it can be read again.

aldo.gia...@gmail.com

unread,
Feb 27, 2015, 10:48:03 AM2/27/15
to golan...@googlegroups.com
Hi Martin,

I think I'm having a similar issue. I started to use Go few weeks ago so bear with me.

I'm doing something similar for a Revel application, I've an interceptor which run before the controller action, read the the body from this ReadCloser and log it to a file.
The problem is that when the action run later, the response body is gone.

I'm wondering if you could post a simple example of how to buffer the body and reassign the response body using ioutil.NopCloser().


Thank you very much for you help.


Aldo

Aldo Giambelluca

unread,
Feb 27, 2015, 11:01:34 AM2/27/15
to golan...@googlegroups.com
Hi, I actually find a way, thanks anyway :)

I also write a small blog post about it, maybe it's useful:
https://medium.com/@xoen/golang-read-from-an-io-readwriter-without-loosing-its-content-2c6911805361


All the best
Aldo
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "golang-nuts" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/golang-nuts/iPfHcpRFc_o/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages