web-dev-qa-db-fra.com

Effectuer une requête encodée en URL POST) en utilisant `http.NewRequest (...)`

Je souhaite faire une demande POST à une API qui envoie mes données sous forme de type de contenu application/x-www-form-urlencoded. Comme je dois gérer les en-têtes de demande, j'utilise la http.NewRequest(method, urlStr string, body io.Reader) méthode pour créer une requête. Pour cela POST requête, j'ajoute ma requête de données à l'URL et laisse le corps vide, quelque chose comme cette:

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

Lorsque je réponds, je reçois toujours un 400 BAD REQUEST. Je pense que le problème repose sur ma demande et que l'API ne comprend pas quelle charge utile je poste. Je connais des méthodes comme Request.ParseForm , je ne sais pas trop comment l'utiliser dans ce contexte. Peut-être suis-je absent d'un autre en-tête, peut-être y a-t-il une meilleure façon d'envoyer des données utiles sous forme de type application/json À l'aide du paramètre body?

80
Fernando Á.

Une charge codée en URL doit être fournie dans le paramètre body de la méthode http.NewRequest(method, urlStr string, body io.Reader), sous la forme d'un type implémentant io.Reader interface.

Basé sur l'exemple de 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("POST", 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")
    r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))

    resp, _ := client.Do(r)
    fmt.Println(resp.Status)
}

resp.Status est 200 OK par ici.

148
Fernando Á.