英文:
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_Golfer和JimB的建议:
io.ReadCloser是一个接口,当一个struct同时实现了Read和Close函数时,它就会被满足。
幸运的是,有一个io.NopCloser函数,它接受一个io.Reader并将其包装在nopCloser结构体中,该结构体同时实现了Read和Close函数。然而,根据名称,它的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("/", 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!`)
}
答案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 := &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).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论