将编组的JSON数据作为URL编码的表单数据进行提交。

huangapple go评论79阅读模式
英文:

Post Marshaled JSON data as URL Encoded Form Data

问题

我正在尝试通过将身份验证结构转换为application/x-www-form-urlencoded数据来发送POST请求。

我尝试过以下方法:

  1. 使用JSON编码的payload缓冲区发送请求,返回错误信息:

    {"error":"invalid_request","error_description":"Missing grant type"}
    
  2. 使用bytes.NewReader和编组的JSON对象,也返回相同的错误信息:

    {"error":"invalid_request","error_description":"Missing grant type"}
    
  3. 使用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:

  1. Sending a JSON encoded payload buffer, which returns

    {"error":"invalid_request","error_description":"Missing grant type"}
    
  2. Using bytes.NewReader with the marshaled JSON object, which also returns

    {"error":"invalid_request","error_description":"Missing grant type"}
    
  3. Using strings.NewReader with the JSON encoded payload buffer, which returns

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

huangapple
  • 本文由 发表于 2022年5月31日 06:17:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/72440525.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定