why return a string here? the caller converts it back to a []byte ? 

For extra credit, return &buf as an io.Reader then use io.Copy to avoid two copies of the entire response body.

For even more credit, return *bytes.Buffer, then you can set the response content length before the io.Copy.

For even even more credit, return an io.Reader, but assert if it matches this interface { Len() int64 } then sett the content length and then do the copy.