0

(go newbie here) I have some code like this:

func (c *clientImpl) queryHost(qtype string, page int) (io.ReadCloser, error) {
    queryURI := c.URL + "/api/query"
    req, _ := http.NewRequest(http.MethodGet, queryURI, nil)
    req.Header.Add(authHeaderName, authToken)
    req.Header.Add("Accept", accept)

    q := req.URL.Query()
    q.Add("type", qtype)
    q.Add("pageSize", pageSize)
    q.Add("page", strconv.Itoa(page))
    req.URL.RawQuery = q.Encode()
    resp, err := c.client.Do(req) //*http.Client
    if err != nil {
        return nil, utils.NestedError("Error in querying Host", err)
    }

    return resp.Body, nil
}

And then called like this:

body, err := c.queryHost(myQType, i)
        if err != nil {
            log.Printf("Error while trying to get page %v - %v \n", i, err)
            return err
        }
        defer body.Close()

        var qResult myQueryResult
        err = xml.NewDecoder(body).Decode(&myQueryResult)
        if err != nil {
            log.Printf("Error while decoding page %v - %v \n", i, err)
            return utils.NestedError("Error in decoding response body xml", err)
        }

I want to log the original xml that was failed to be processed, but since this is a ReadCloser and once read, it cannot be read again (or am I wrong?). Is there a way I can get this, or do I have to store the initial response somewhere and pass copies around?

Mario Stoilov
  • 3,411
  • 5
  • 31
  • 51

2 Answers2

4
  1. Read bytes with io/ioutil ReadAll

    defer body.Close()

    data, err := ioutil.ReadAll(body)

  2. Then unmarshal

    err = xml.Unmarshal(data, &qResult)

You can log data for checking original xml.

Anupam
  • 869
  • 7
  • 13
  • While this DOES work, please specify that it returns `[]byte` not a string and should use something like this -> http://stackoverflow.com/questions/14230145/what-is-the-best-way-to-convert-byte-array-to-string to convert it – Mario Stoilov Sep 09 '16 at 12:50
  • True, but in this case since unmarhsal accepts []byte and it wasn't required. https://golang.org/pkg/encoding/xml/#Unmarshal – Anupam Sep 09 '16 at 12:55
0

For http responses you can use the httputil package's DumpResponse:

Example from the link:

package main

import (
    "fmt"
    "log"
    "net/http"
    "net/http/httptest"
    "net/http/httputil"
)

func main() {
    const body = "Go is a general-purpose language designed with systems programming in mind."
    ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Date", "Wed, 19 Jul 1972 19:00:00 GMT")
        fmt.Fprintln(w, body)
    }))
    defer ts.Close()

    resp, err := http.Get(ts.URL)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()

    dump, err := httputil.DumpResponse(resp, true)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%q", dump)

}
Kyle Brandt
  • 26,938
  • 37
  • 124
  • 165