2016-10-12 103 views
4

创建我的形式是这样的:发送POST请求Golang与头

form := url.Values{} 
form.Add("region", "San Francisco") 
if len(params) > 0 { 
    for i := 0; i < len(params); i += 2 { 
     form.Add(params[i], params[i+1]) 
    } 
    testLog.Infof("form %v", form) 

现在,如果我用

resp, err = http.PostForm(address+r.Path, form) 

然后一切工作正常,我回来与预期的cookie的响应。

不过,我想补充在这种情况下,我不能使用PostForm所以我创造了我的POST request手动像头:

req, err := http.NewRequest("POST", address+r.Path, strings.NewReader(form.Encode())) 

然后我添加的东西页眉和发送请求

req.Header.Add("region", "San Francisco") 
resp, err = http.DefaultClient.Do(req) 

但表单没有收到,我的回复没有包含任何cookie。

当我打印req,它看起来像形式是nil

&{POST http://localhost:8081/login HTTP/1.1 1 1 map[Region:[San Francisco]] {0xc420553600} 78 [] false localhost:8081 map[] map[] <nil> map[] <nil> <nil> <nil> <nil>} 
+0

这是一个网页上发布的形式,对不对?如果是这样的话,你将不得不使用JS。当您使用模板时,Go代码不会发布任何内容,只需使用类型为submit的输入元素生成html。另一方面,该请求无法在浏览器中运行,它必须在系统上运行。因此,如果您使用提交到POST后端的HTML表单并且想要添加标题,则需要在JavaScript中使用“XMLHttpRequest”来完成此操作。 – evanmcdonnal

+0

不,不是网页,这是一个Go单元测试。看到下面的答案,设置头中的内容类型解决了我的问题。 – Jana

回答

10

您需要的内容类型添加到您的请求。

你说http.PostForm工作所以让我们看看该source

func PostForm(url string, data url.Values) (resp *Response, err error) { 
    return DefaultClient.PostForm(url, data) 
} 

OK所以它只是周围的默认客户端上的PostForm方法的包装。让我们来看看that

func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) { 
    return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) 
} 

确定它调用了Post方法和"application/x-www-form-urlencoded"通过为bodyType,做对你做的身体同样的事情。让我们来看看the Post method

func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *Response, err error) { 
    req, err := NewRequest("POST", url, body) 
    if err != nil { 
     return nil, err 
    } 
    req.Header.Set("Content-Type", bodyType) 
    return c.doFollowingRedirects(req, shouldRedirectPost) 
} 

因此,解决问题的方法是添加

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