使用golang创建带有示例字符串的http.Response实例

33
我愿意在golang中创建一个带有示例字符串正文的http.Response实例。
问题是,它的正文属性接受ReadCloser实例。但由于这是一个虚拟响应实例,我想知道是否有一些技巧可以轻松设置它,而不必设置所有流读取/关闭部分。

3
您可以使用简单的字符串读取器或类似的东西,并附加一个虚拟的 Close 方法来扩展它。 - Not_a_Golfer
6
这是为你准备的:ioutil.NopCloser - JimB
现在您可以使用 http.NoBody - wijayaerick
4个回答

59

正如Not_a_GolferJimB所建议的:

io.ReadCloser是一个接口,当一个struct同时实现了ReadClose函数时,它就被满足。

幸运的是,有一个io.NopCloser,它接受一个io.Reader并将其包装在nopCloser结构体中,该结构体同时实现了ReadClose。然而,根据名称,它的Close函数什么也不做。

这里是一个例子:

package main

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

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

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

    fmt.Println(buff)
}

要玩代码,请点击这里


25

进一步回答,我发现为了让客户端将响应视为真实的文章,需要更充分地形成它。对于正常(200)响应,我执行以下操作:

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),
}

然后,你可以例如添加头信息(使用 401 状态码,请求授权等)。req 是你正在生成响应的 http.Request


3

这应该可以正常工作。

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!`)
}

1
这是我个人认为最简单的答案。 - user11809641

2

是的,ioutil.NopCloser正是我需要的!

我正在尝试测试一个调用Facebook API的方法(通过帮助函数)来进行社交连接端点,并且我想模拟来自帮助函数的Facebook响应,因此我的解决方案如下:

期望的Facebook响应(转换为我的UserData结构)如下:

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

所以我像这样创建了预期的响应:
fbUserData, _ := json.Marshal(UserData{
    ID:        facebookID,
    Email:     email,
    FirstName: firstName,
    LastName:  lastName,
})
fbUserDataResponse := &http.Response{
    Body: ioutil.NopCloser(bytes.NewBufferString(string(fbUserData))),
}

然后,我可以像这样模拟调用 Facebook API 的方法的响应:
s.fbGateway.EXPECT().ExecuteGetQuery(userUrl).Return(fbUserDataResponse, nil).Times(1)

这里的重点是模拟任何返回*http.Response数据的函数(在我的情况下,我通过一个返回http响应的帮助函数调用Facebook API,如上所述)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接