133 votes

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

Je veux faire une requête POST à une API en envoyant mes données avec un type de contenu application/x-www-form-urlencoded. En raison du fait que j'ai besoin de gérer les en-têtes de la requête, j'utilise la méthode http.NewRequest(method, urlStr string, body io.Reader) pour créer une requête. Pour cette requête POST, j'ajoute ma requête de données à l'URL et laisse le corps vide, quelque chose comme ceci :

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

En réponse, je reçois toujours un 400 BAD REQUEST. Je crois que le problème vient de ma requête et que l'API ne comprend pas quelle charge utile je suis en train de poster. Je suis au courant de méthodes comme Request.ParseForm, mais je ne suis pas vraiment sûr de comment l'utiliser dans ce contexte. Peut-être que je manque un autre en-tête, peut-être y a-t-il une meilleure façon d'envoyer une charge utile de type application/json en utilisant le paramètre body ?

245voto

Fernando Á. Points 820

La charge utile encodée en URL doit être fournie sur le paramètre body de la méthode http.NewRequest(method, urlStr string, body io.Reader), en tant que type qui implémente l'interface io.Reader.

Basé sur le code d'exemple:

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())) // Charge utile encodée en URL
    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 est 200 OK de cette manière.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X