`` Http.NewRequest (…) '' kullanarak URL kodlu bir POST isteği yapın


98

Verilerimi application/x-www-form-urlencodediçerik türü olarak gönderen bir API'ye POST isteğinde bulunmak istiyorum . İstek başlıklarını yönetmem gerektiği için, http.NewRequest(method, urlStr string, body io.Reader)bir istek oluşturmak için yöntemi kullanıyorum . Bu POST isteği için veri sorgumu URL'ye ekliyorum ve gövdeyi boş bırakıyorum, şöyle bir şey:

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

Cevap verdiğimde, her zaman bir 400 BAD REQUEST. Sorunun isteğime bağlı olduğuna ve API'nin hangi yükü gönderdiğimi anlamadığına inanıyorum. Request.ParseFormBu bağlamda nasıl kullanılacağından emin değilim gibi yöntemlerin farkındayım . Belki biraz daha fazla Başlık eksik olabilir, belki application/jsonde bodyparametreyi kullanarak bir tür olarak yük göndermenin daha iyi bir yolu var mı?

Yanıtlar:


189

URL kodlu yük , arayüzü uygulayan bir tür olarak yöntemin bodyparametresinde sağlanmalıdır .http.NewRequest(method, urlStr string, body io.Reader)io.Reader

Örnek koda göre:

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")
    r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))

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

resp.Statusolan 200 OKbu taraftan.


2
ya herhangi bir veri göndermek istemiyorsam ?? `` Bytes.NewBufferString (data.Encode ()) '' yerine herhangi bir sahte veri gönderirsem, çalışır mı?
Aditya Peshave

Boş bir * Buffer göndermeye çalışırdım: örneğin bverilenvar b bytes.Buffer
Fernando Á.

4
Zaten Content-Lenghtolduğu gibi başlığı ayarlamanıza gerek http.NewRequestyoktur.
dvdplm

12
Bunun strings.NewReader(data.Encode())yerine (daha verimli) kullanabileceğimizi düşünüyorum bytes.NewBufferString(data.Encode()). At * Okuyucu NewReader (ler dize) fonk , diyor "NewReader s okuma yeni Reader döndürür. Bu bytes.NewBufferString benzer ancak salt okunur daha verimli ve olduğunu."
Liyang Chen

1
data.Setyerine hem nameve için kullanılmalıdır . Aynı anahtara başka bir değer eklemek yerine anahtarın değerini ayarlar . da çalışır, ancak dilimi boşaltmak gereksizdir . surnamedata.Adddata.AddAddappend(v[key], value)
metalim
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.