为什么我的 GoLang POST 请求没有填充数据?

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

Why isn't my GoLang POST request being populated with data?

问题

func forwarderHandlerFunc(w http.ResponseWriter, r *http.Request) {
client := &http.Client{}
u, _ := url.Parse(r.RequestURI)
req, _ := http.NewRequest(r.Method, fmt.Sprintf("%s%s", apiUrl, u.Path), r.Body)
fmt.Printf(fmt.Sprintf("%s\n", nutils.ReaderToString(req.Body)))
resp, _ := client.Do(req)
resp.Write(w)
}

我正在尝试将传入的HTTP请求转发到另一个端点,同时将请求体,包括POST/PUT表单数据,复制到新的请求中。

然而,似乎不起作用,即使请求体的打印输出看起来是正确的。

打印输出为:

email=meh%!g(MISSING)mail.com

我该如何修复它?


编辑:添加了更多的调试信息,这次打印出了resp的输出

func forwarderHandlerFunc(w http.ResponseWriter, r *http.Request) {
client := &http.Client{}
u, _ := url.Parse(r.RequestURI)

req, _ := http.NewRequest(r.Method, fmt.Sprintf("%s%s", apiUrl, u.Path), r.Body)
fmt.Printf(fmt.Sprintf("%s\n", nutils.ReaderToString(req.Body)))

resp, _ := client.Do(req)
b,_ := ioutil.ReadAll(resp.Body)
fmt.Printf(fmt.Sprintf("%s\n", nutils.BytesToString(b)))

resp.Write(w)

}

$ go install && gom-proxy-forwarder run --listen localhost:5002 --api-url http://localhost:5001
email=meh2%!g(MISSING)mail.com
{
"email": null
}

它不应该是null。它应该是meh@gmail.com

英文:
func forwarderHandlerFunc(w http.ResponseWriter, r *http.Request) {
	client := &http.Client{}
	u, _ := url.Parse(r.RequestURI)
	req, _ := http.NewRequest(r.Method, fmt.Sprintf("%s%s", apiUrl, u.Path), r.Body)
	fmt.Printf(fmt.Sprintf("%s\n", nutils.ReaderToString(req.Body)))
	resp, _ := client.Do(req)
	resp.Write(w)
}

I am trying to forward an incoming HTTP request to another endpoint, while copying the body, including POST/PUT form data into the new request.

However, it doesn't seem to work, even if the Body seems to print out correct with data.

Print output is:

> email=meh%!g(MISSING)mail.com

How can I fix it?


Edit: Added more debug info, this time, printing out the output of resp

func forwarderHandlerFunc(w http.ResponseWriter, r *http.Request) {
	client := &http.Client{}
	u, _ := url.Parse(r.RequestURI)

	req, _ := http.NewRequest(r.Method, fmt.Sprintf("%s%s", apiUrl, u.Path), r.Body)
    fmt.Printf(fmt.Sprintf("%s\n", nutils.ReaderToString(req.Body)))

	resp, _ := client.Do(req)
	b,_ := ioutil.ReadAll(resp.Body)
	fmt.Printf(fmt.Sprintf("%s\n", nutils.BytesToString(b)))

	resp.Write(w)
}

> $ go install && gom-proxy-forwarder run --listen localhost:5002 --api-url http://localhost:5001
> email=meh2%!g(MISSING)mail.com
> {
> "email": null
> }

It should not be null. It should be meh@gmail.com

答案1

得分: 4

明白了。问题是我在Python的Flask服务器中的端点不支持分块编码,而Go的请求坚持要使用分块编码。

当我手动指定ContentLength,比如req.ContentLength = 25,它就可以工作了。

教训是:问题可能不总是出在你的Go代码上。

英文:

Got it. The problem was my endpoint in Python's Flask server does not support chunked encoding, which Go's Request insists on.

When I manually specified the ContentLength like req.ContentLength = 25, it worked.

Lesson learnt: It might not always be your Go code be the problem.

答案2

得分: 0

你可能想要设置请求的内容类型:

req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

参考链接:http://golang.org/src/net/http/client.go?s=14234:14316#L450

英文:

You may want to set the request content type

req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

reference http://golang.org/src/net/http/client.go?s=14234:14316#L450

答案3

得分: 0

要修复你的打印输出,你需要将这段代码更改为:

fmt.Printf("%s", fmt.Sprintf("%s\n", nutils.ReaderToString(req.Body)))

或者这样:

fmt.Println(fmt.Sprintf("%s\n", nutils.ReaderToString(req.Body)))

通过打印请求体,你正在消耗它。使用TeeReader

req, _ := http.NewRequest(r.Method, fmt.Sprintf("%s%s", apiUrl, u.Path), io.TeeReader(r.Body, os.Stdout))

并且去掉nutils.ReaderToString的调用。你只能从一个Reader中读取一次(除非它也是一个Seeker,但在重新使用之前仍然需要调用Seek)。

英文:
  1. To fix your print output you need to change this:

     fmt.Printf(fmt.Sprintf("%s\n", nutils.ReaderToString(req.Body)))
    

    Into this:

     fmt.Printf("%s", fmt.Sprintf("%s\n", nutils.ReaderToString(req.Body)))
    

    Or this:

     fmt.Println(fmt.Sprintf("%s\n", nutils.ReaderToString(req.Body)))
    
  2. By printing out the request body you are consuming it. Use a TeeReader:

     req, _ := http.NewRequest(r.Method, fmt.Sprintf("%s%s", apiUrl, u.Path), io.TeeReader(r.Body, os.Stdout))
    

    And get rid of the nutils.ReaderToString call. You can only read once from a Reader (unless it's also a Seeker but then you still need to Seek it before reusing it)

huangapple
  • 本文由 发表于 2015年5月20日 11:41:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/30339877.html
匿名

发表评论

匿名网友

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

确定