`Http.NewRequest (…)` का उपयोग करके URL-एन्कोडेड POST अनुरोध करें


94

मैं अपने डेटा को application/x-www-form-urlencodedसामग्री प्रकार के रूप में भेजने वाले API के लिए एक POST अनुरोध करना चाहता हूं । इस तथ्य के कारण कि मुझे अनुरोध शीर्षलेख प्रबंधित करने की आवश्यकता है, मैं http.NewRequest(method, urlStr string, body io.Reader)अनुरोध बनाने के लिए विधि का उपयोग कर रहा हूं । इस पोस्ट अनुरोध के लिए मैं URL पर अपनी डेटा क्वेरी संलग्न करता हूं और शरीर को खाली छोड़ देता हूं, कुछ इस तरह से:

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

प्रतिक्रिया के रूप में, मुझे हमेशा ए मिलता है 400 BAD REQUEST। मेरा मानना ​​है कि समस्या मेरे अनुरोध पर निर्भर करती है और एपीआई को समझ में नहीं आता है कि मैं कौन सा पेलोड पोस्ट कर रहा हूं। मुझे इस तरह के तरीकों के बारे में पता है Request.ParseForm, वास्तव में यकीन नहीं है कि इस संदर्भ में इसका उपयोग कैसे करें। शायद मुझे कुछ और हैडर याद आ रहे हैं, शायद पैरामीटर application/jsonका उपयोग करके पेलोड को एक प्रकार के रूप में भेजने का एक बेहतर तरीका है body?

जवाबों:


182

URL-एन्कोडेड पेलोड को एक प्रकार के इंटरफ़ेस के रूप bodyमें http.NewRequest(method, urlStr string, body io.Reader)विधि के पैरामीटर पर प्रदान किया जाना चाहिए io.Reader

नमूना कोड के आधार पर:

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.Statusहै 200 OKइस तरह से।


2
क्या होगा अगर मैं कोई डेटा नहीं भेजना चाहता हूँ ?? यदि मैं `bytes.NewBufferString (data.Encode ())` के स्थान पर कोई डमी डेटा भेजता हूं, तो क्या यह काम करेगा?
आदित्य पेशव

मैं एक खाली * बफर भेजने की कोशिश करूँगा: जैसे bदिया गयाvar b bytes.Buffer
फर्नांडो

4
आपको Content-Lenghtशीर्ष लेख सेट करने की आवश्यकता नहीं है , जैसा http.NewRequestकि पहले से ही है।
डीवीडीप्लम

12
मुझे लगता है कि हम strings.NewReader(data.Encode())इसके बजाय (अधिक कुशल) उपयोग कर सकते हैं bytes.NewBufferString(data.Encode())। पर समारोह NewReader (रों स्ट्रिंग) * रीडर , यह कहते हैं, "NewReader एक नया रीडर रों से पढ़ने देता है। यह bytes.NewBufferString के समान है, लेकिन अधिक कुशल और केवल पढ़ने के लिए है।"
लियांग चेन

1
data.Setके बजाय दोनों के लिए nameऔर इस्तेमाल किया जाना चाहिए । यह कुंजी का मान सेट करता है, इसके बजाय उसी कुंजी के लिए एक और मूल्य जोड़ता है, जैसा कि करता है। भी काम करता है, लेकिन खाली स्लाइस के लिए अनावश्यक है। surnamedata.Adddata.AddAddappend(v[key], value)
मेटल डेम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.