Andy Stewart
Andy Stewart

Reputation: 5498

How to write an HTTP response to stdout?

I am trying to write to stdout the raw HTTP response received from a GET request. I thought httputil.DumpResponse would do what I want but it seems to include mysterious byte counts on "bigger" responses.

For example:

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/plain; charset=utf-8
Date: Mon, 16 Oct 2017 15:07:53 GMT

1f43
THE ACTUAL BODY CONTENT WHICH IS 8003 BYTES
0

The 1f43 seems to be the length of the response body. Go's http.response talks about trailers, so maybe the 0 is the size of the trailer.

My code is:

    var resp *http.Response
    var err error

    if *isPost {
        resp, err = http.Post(url, "application/x-www-form-urlencoded", strings.NewReader(*data))
    } else {
        resp, err = http.Get(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("%s", dump)

I have read the code for DumpResponse and TransferWriter but I can't figure out where the 1f43 and 0 come from.

If I make the same request with curl, I don't get the 1f43 and 0 in the response.

Is this the best way to write the raw HTTP response? If so, how can I fix it to avoid these byte counts?

Upvotes: 2

Views: 2910

Answers (1)

gritt
gritt

Reputation: 78

You can use interfaces for that,

The http.Get call returns a pointer to a Response type, which contains a Body, if you check Body interfaces, you can see that the Body implements the io.ReadCloser, which, implements both the Reader and Closer interfaces;

By understanding these interfaces you can make use of eg: io.Copy

func Copy(dst Writer, src Reader) (written int64, err error) {...}

As second argument, you could pass the Response Body, which implements the Reader.

As first argument, Writer, you could both implement your own custom type, and create a func to implement the Writer interface, or, you can also use the built in os.Stdout, which already implements it.

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {

    resp, err := http.Get("http://google.com")

    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(1)
    }

    io.Copy(os.Stdout, resp.Body)
}

Upvotes: 3

Related Questions