Create http.Response instance with sample body string in golang

31,190

Solution 1

As suggested by Not_a_Golfer and JimB:

io.ReadCloser is an interface that is satisfied when a struct implements both the Read and the Close functions.

Fortunately, there is ioutil.NopCloser, which takes a io.Reader and wraps it in the nopCloser struct, which implements both Read and Close. However, its Close function does nothing as implied from the name.

Here is an example:

package main

import (
    "bytes"
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    t := http.Response{
        Body: ioutil.NopCloser(bytes.NewBufferString("Hello World")),
    }

    buff := bytes.NewBuffer(nil)
    t.Write(buff)

    fmt.Println(buff)
}

To play with the code, click here.

Solution 2

Further to the top answer, I have found that in order for the response to be treated as the genuine article by clients, it needs to be more fully formed. For a normal (200) response, I do the following:

body := "Hello world"
t := &http.Response{
  Status:        "200 OK",
  StatusCode:    200,
  Proto:         "HTTP/1.1",
  ProtoMajor:    1,
  ProtoMinor:    1,
  Body:          ioutil.NopCloser(bytes.NewBufferString(body)),
  ContentLength: int64(len(body)),
  Request:       req,
  Header:        make(http.Header, 0),
}

Then you can, for example, add headers (with a 401 status code, to ask for authorisation, say). req is the http.Request for which you are generating the response.

Solution 3

This should work..

func main(){

    go serveHTTP(*port, *host)

    select {}
}

func serveHTTP(port int, host string) {

    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        requestHandler(w, r)
    })

    addr := fmt.Sprintf("%v:%d", host, port)
    server := &http.Server {
        Addr:           addr,
        Handler:        mux,
        ReadTimeout:    10 * time.Second,
        WriteTimeout:   10 * time.Second,
        MaxHeaderBytes: 1 << 20,
    }

    err := server.ListenAndServe()
    log.Println(err.Error())
}

func requestHandler(w http.ResponseWriter, r *http.Request){
  fmt.Fprintf(w, `Success!`)
}

Solution 4

Yes, the ioutil.NopCloser is just what I needed!

Am trying to test a method that performs calls to the facebook API (via a helper function) for a social-connect endpoint, and I want to mock the facebook response coming from the helper function, so my solution is like follows:

Expected facebook response (converted to my own UserData struct) is:

UserData {
    ID:        facebookID,
    Email:     email,
    FirstName: firstName,
    LastName:  lastName,
}

So I create the expected response like this:

fbUserData, _ := json.Marshal(UserData{
    ID:        facebookID,
    Email:     email,
    FirstName: firstName,
    LastName:  lastName,
})
fbUserDataResponse := &http.Response{
    Body: ioutil.NopCloser(bytes.NewBufferString(string(fbUserData))),
}

Then I can mock the response for the method calling the facebook API like this:

s.fbGateway.EXPECT().ExecuteGetQuery(userUrl).Return(fbUserDataResponse, nil).Times(1)

The point here is that this is really about mocking any kind of functions that return *http.Response data (in my case I am calling the facebook API via a helper function that returns the http Response, as mentioned above).

Share:
31,190
Rana
Author by

Rana

Software Engineer, Technology Enthusiast, Blogger.

Updated on April 02, 2020

Comments

  • Rana
    Rana about 4 years

    I am willing to create a sample http.Response instance in golang with a sample body string.

    Problem is, its body property accepts ReadCloser instance. But as its a dummy response instance, I was wondering if there is some trick to set it easily without setting up all that stream read/close parts.