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

huangapple go评论71阅读模式
英文:

Create http.Response instance with sample body string in golang

问题

我愿意在golang中创建一个带有示例body字符串的http.Response实例。

问题是,它的body属性接受ReadCloser实例。但由于它是一个虚拟的响应实例,我想知道是否有一些技巧可以轻松设置它,而不需要设置所有的流读取/关闭部分。

英文:

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.

答案1

得分: 58

根据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)
}

要尝试运行这段代码,请点击这里

英文:

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 io.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"
    "net/http"
)

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

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

	fmt.Println(buff)
}

To play with the code, click here.

答案2

得分: 23

根据顶部的答案,我发现为了让响应被客户端视为真实的文章,它需要更完整的形式。对于正常的(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

英文:

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.

答案3

得分: 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, `成功!`)
}
英文:

This should work..

func main(){

	go serveHTTP(*port, *host)

	select {}
}

func serveHTTP(port int, host string) {
	
	mux := http.NewServeMux()
	mux.HandleFunc(&quot;/&quot;, func(w http.ResponseWriter, r *http.Request) {
		requestHandler(w, r)
	})

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

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

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

答案4

得分: 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)。

英文:

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 := &amp;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).

huangapple
  • 本文由 发表于 2015年11月29日 08:57:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/33978216.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定