英文:
Post Marshaled JSON data as URL Encoded Form Data
问题
我正在尝试通过将身份验证结构转换为application/x-www-form-urlencoded
数据来发送POST请求。
我尝试过以下方法:
-
使用JSON编码的payload缓冲区发送请求,返回错误信息:
{"error":"invalid_request","error_description":"Missing grant type"}
-
使用
bytes.NewReader
和编组的JSON对象,也返回相同的错误信息:{"error":"invalid_request","error_description":"Missing grant type"}
-
使用
strings.NewReader
和JSON编码的payload缓冲区,返回错误信息:cannot use payloadBuf (variable of type *bytes.Buffer) as type string in argument to strings.NewReader
对应的curl请求如下:
curl --request POST \
--url https://api.io/v1/oauth/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data 'username=email' \
--data 'password=pass' \
--data 'grant_type=password' \
--data 'scope=SPACE SEPARATED STRINGS'
并且以下代码可以正常工作:
package main
import (
"io/ioutil"
"log"
"net/http"
"net/url"
"strings"
)
func main() {
const endpoint string = "https://api.io/v1/oauth/token"
payload := url.Values{
"username": {"email"},
"password": {"pass"},
"grant_type": {"password"},
"scope": {"SPACE SEPARATED STRINGS"},
}
req, err := http.NewRequest("POST", endpoint, strings.NewReader(payload.Encode()))
if err != nil {
log.Printf("Unable to perform POST request:\n%v", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
log.Println(string(body))
}
请问如何将编组的JSON数据作为application/x-www-form-urlencoded
发送POST请求?
英文:
I'm trying to send a POST request by converting an auth structure to application/x-www-form-urlencoded
data.
package main
import (
"bytes"
"encoding/json"
"io/ioutil"
"log"
"net/http"
)
type Payload struct {
Username string `json:"username"`
Password string `json:"password"`
GrantType string `json:"grant_type"`
Scope string `json:"scope"`
}
func main() {
var endpoint string = "https://api.io/v1/oauth/token"
jsonPay := &Payload{
Username: "email",
Password: "pass",
GrantType: "password",
Scope: "SPACE SEPARATED STRINGS",
}
//byteArr, err := json.Marshal(jsonPay)
//if err != nil {
// log.Printf("Unable to map structure\n%v", err)
//}
payloadBuf := new(bytes.Buffer)
json.NewEncoder(payloadBuf).Encode(jsonPay)
req, err := http.NewRequest("POST", endpoint, payloadBuf)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
log.Printf(string(body))
}
I've tried:
-
Sending a JSON encoded payload buffer, which returns
{"error":"invalid_request","error_description":"Missing grant type"}
-
Using
bytes.NewReader
with the marshaled JSON object, which also returns{"error":"invalid_request","error_description":"Missing grant type"}
-
Using
strings.NewReader
with the JSON encoded payload buffer, which returnscannot use payloadBuf (variable of type *bytes.Buffer) as type string in argument to strings.NewReader
The curl request looks like:
curl --request POST \
--url https://api.io/v1/oauth/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data 'username=email' \
--data 'password=pass' \
--data 'grant_type=password' \
--data 'scope=SPACE SEPARATED STRINGS'
and works with:
package main
import (
"io/ioutil"
"log"
"net/http"
"net/url"
"strings"
)
func main() {
const endpoint string = "https://api.io/v1/oauth/token"
payload := url.Values{
"username": {"email"},
"password": {"pass"},
"grant_type": {"password"},
"scope": {"SPACE SEPARATED STRINGS"},
}
req, err := http.NewRequest("POST", endpoint, strings.NewReader(payload.Encode()))
if err != nil {
log.Printf("Unable to perform POST request:\n%v", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
log.Println(string(body))
}
How do I post marshaled JSON data as application/x-www-form-urlencoded
答案1
得分: 0
实施了@RedBlue的建议:
package main
import (
"io/ioutil"
"log"
"net/http"
"strings"
"net/url"
)
type Payload struct {
Username string `json:"username"`
Password string `json:"password"`
GrantType string `json:"grant_type"`
Scope string `json:"scope"`
}
func main() {
const endpoint string = "https://api.io/v1/oauth/token"
formData := &Payload{
Username: "email",
Password: "pass",
GrantType: "password",
Scope: "SPACE SEPARATED STRINGS",
}
payload := url.Values{
"username": {formData.Username},
"password": {formData.Password},
"grant_type": {formData.GrantType},
"scope": {formData.Scope},
}
req, err := http.NewRequest("POST", endpoint, strings.NewReader(payload.Encode()))
if err != nil {
log.Printf("无法执行POST请求:\n%v", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
log.Println(string(body))
}
英文:
Implemented @RedBlue's suggestion:
package main
import (
"io/ioutil"
"log"
"net/http"
"strings"
"net/url"
)
type Payload struct {
Username string `json:"username"`
Password string `json:"password"`
GrantType string `json:"grant_type"`
Scope string `json:"scope"`
}
func main() {
const endpoint string = "https://api.io/v1/oauth/token"
formData := &Payload{
Username: "email",
Password: "pass",
GrantType: "password",
Scope: "SPACE SEPARATED STRINGS",
}
payload := url.Values{
"username": {formData.Username},
"password": {formData.Password},
"grant_type": {formData.GrantType},
"scope": {formData.Scope},
}
req, err := http.NewRequest("POST", endpoint, strings.NewReader(payload.Encode()))
if err != nil {
log.Printf("Unable to perform POST request:\n%v", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
log.Println(string(body))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论