Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a URL-encoded POST request using `http.NewRequest(...)`

Tags:

http

go

I want to make a POST request to an API sending my data as a application/x-www-form-urlencoded content type. Due to the fact that I need to manage the request headers, I'm using the http.NewRequest(method, urlStr string, body io.Reader) method to create a request. For this POST request I append my data query to the URL and leave the body empty, something like this:

package main  import (     "bytes"     "fmt"     "net/http"     "net/url"     "strconv" )  func main() {     apiUrl := "https://api.com"     resource := "/user/"     data := url.Values{}     data.Set("name", "foo")     data.Add("surname", "bar")      u, _ := url.ParseRequestURI(apiUrl)     u.Path = resource     u.RawQuery = data.Encode()     urlStr := fmt.Sprintf("%v", u) // "https://api.com/user/?name=foo&surname=bar"      client := &http.Client{}     r, _ := http.NewRequest("POST", urlStr, nil)     r.Header.Add("Authorization", "auth_token=\"XXXXXXX\"")     r.Header.Add("Content-Type", "application/x-www-form-urlencoded")     r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))      resp, _ := client.Do(r)     fmt.Println(resp.Status) } 

As I response, I get always a 400 BAD REQUEST. I believe the problem relies on my request and the API does not understand which payload I am posting. I'm aware of methods like Request.ParseForm, not really sure how to use it in this context though. Maybe am I missing some further Header, maybe is there a better way to send payload as a application/json type using the body parameter?

like image 747
Fernando Á. Avatar asked Oct 08 '13 16:10

Fernando Á.


1 Answers

URL-encoded payload must be provided on the body parameter of the http.NewRequest(method, urlStr string, body io.Reader) method, as a type that implements io.Reader interface.

Based on the sample code:

package main  import (     "fmt"     "net/http"     "net/url"     "strconv"     "strings" )  func main() {     apiUrl := "https://api.com"     resource := "/user/"     data := url.Values{}     data.Set("name", "foo")     data.Set("surname", "bar")      u, _ := url.ParseRequestURI(apiUrl)     u.Path = resource     urlStr := u.String() // "https://api.com/user/"      client := &http.Client{}     r, _ := http.NewRequest(http.MethodPost, urlStr, strings.NewReader(data.Encode())) // URL-encoded payload     r.Header.Add("Authorization", "auth_token=\"XXXXXXX\"")     r.Header.Add("Content-Type", "application/x-www-form-urlencoded")      resp, _ := client.Do(r)     fmt.Println(resp.Status) } 

resp.Status is 200 OK this way.

like image 64
Fernando Á. Avatar answered Sep 18 '22 12:09

Fernando Á.