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

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

Post Marshaled JSON data as URL Encoded Form Data

问题

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

我尝试过以下方法:

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

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

    1. {"error":"invalid_request","error_description":"Missing grant type"}
  3. 使用strings.NewReader和JSON编码的payload缓冲区,返回错误信息:

    1. cannot use payloadBuf (variable of type *bytes.Buffer) as type string in argument to strings.NewReader

对应的curl请求如下:

  1. curl --request POST \
  2. --url https://api.io/v1/oauth/token \
  3. --header 'Content-Type: application/x-www-form-urlencoded' \
  4. --data 'username=email' \
  5. --data 'password=pass' \
  6. --data 'grant_type=password' \
  7. --data 'scope=SPACE SEPARATED STRINGS'

并且以下代码可以正常工作:

  1. package main
  2. import (
  3. "io/ioutil"
  4. "log"
  5. "net/http"
  6. "net/url"
  7. "strings"
  8. )
  9. func main() {
  10. const endpoint string = "https://api.io/v1/oauth/token"
  11. payload := url.Values{
  12. "username": {"email"},
  13. "password": {"pass"},
  14. "grant_type": {"password"},
  15. "scope": {"SPACE SEPARATED STRINGS"},
  16. }
  17. req, err := http.NewRequest("POST", endpoint, strings.NewReader(payload.Encode()))
  18. if err != nil {
  19. log.Printf("Unable to perform POST request:\n%v", err)
  20. }
  21. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  22. req.Header.Add("Accept", "application/json")
  23. resp, err := http.DefaultClient.Do(req)
  24. if err != nil {
  25. log.Fatal(err)
  26. }
  27. defer resp.Body.Close()
  28. body, err := ioutil.ReadAll(resp.Body)
  29. if err != nil {
  30. log.Fatal(err)
  31. }
  32. log.Println(string(body))
  33. }

请问如何将编组的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.

  1. package main
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "io/ioutil"
  6. "log"
  7. "net/http"
  8. )
  9. type Payload struct {
  10. Username string `json:"username"`
  11. Password string `json:"password"`
  12. GrantType string `json:"grant_type"`
  13. Scope string `json:"scope"`
  14. }
  15. func main() {
  16. var endpoint string = "https://api.io/v1/oauth/token"
  17. jsonPay := &Payload{
  18. Username: "email",
  19. Password: "pass",
  20. GrantType: "password",
  21. Scope: "SPACE SEPARATED STRINGS",
  22. }
  23. //byteArr, err := json.Marshal(jsonPay)
  24. //if err != nil {
  25. // log.Printf("Unable to map structure\n%v", err)
  26. //}
  27. payloadBuf := new(bytes.Buffer)
  28. json.NewEncoder(payloadBuf).Encode(jsonPay)
  29. req, err := http.NewRequest("POST", endpoint, payloadBuf)
  30. if err != nil {
  31. log.Fatal(err)
  32. }
  33. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  34. req.Header.Add("Accept", "application/json")
  35. resp, err := http.DefaultClient.Do(req)
  36. if err != nil {
  37. log.Fatal(err)
  38. }
  39. defer resp.Body.Close()
  40. body, err := ioutil.ReadAll(resp.Body)
  41. if err != nil {
  42. log.Fatal(err)
  43. }
  44. log.Printf(string(body))
  45. }

I've tried:

  1. Sending a JSON encoded payload buffer, which returns

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

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

    1. cannot use payloadBuf (variable of type *bytes.Buffer) as type string in argument to strings.NewReader

The curl request looks like:

  1. curl --request POST \
  2. --url https://api.io/v1/oauth/token \
  3. --header 'Content-Type: application/x-www-form-urlencoded' \
  4. --data 'username=email' \
  5. --data 'password=pass' \
  6. --data 'grant_type=password' \
  7. --data 'scope=SPACE SEPARATED STRINGS'

and works with:

  1. package main
  2. import (
  3. "io/ioutil"
  4. "log"
  5. "net/http"
  6. "net/url"
  7. "strings"
  8. )
  9. func main() {
  10. const endpoint string = "https://api.io/v1/oauth/token"
  11. payload := url.Values{
  12. "username": {"email"},
  13. "password": {"pass"},
  14. "grant_type": {"password"},
  15. "scope": {"SPACE SEPARATED STRINGS"},
  16. }
  17. req, err := http.NewRequest("POST", endpoint, strings.NewReader(payload.Encode()))
  18. if err != nil {
  19. log.Printf("Unable to perform POST request:\n%v", err)
  20. }
  21. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  22. req.Header.Add("Accept", "application/json")
  23. resp, err := http.DefaultClient.Do(req)
  24. if err != nil {
  25. log.Fatal(err)
  26. }
  27. defer resp.Body.Close()
  28. body, err := ioutil.ReadAll(resp.Body)
  29. if err != nil {
  30. log.Fatal(err)
  31. }
  32. log.Println(string(body))
  33. }

How do I post marshaled JSON data as application/x-www-form-urlencoded

答案1

得分: 0

实施了@RedBlue的建议:

  1. package main
  2. import (
  3. "io/ioutil"
  4. "log"
  5. "net/http"
  6. "strings"
  7. "net/url"
  8. )
  9. type Payload struct {
  10. Username string `json:"username"`
  11. Password string `json:"password"`
  12. GrantType string `json:"grant_type"`
  13. Scope string `json:"scope"`
  14. }
  15. func main() {
  16. const endpoint string = "https://api.io/v1/oauth/token"
  17. formData := &Payload{
  18. Username: "email",
  19. Password: "pass",
  20. GrantType: "password",
  21. Scope: "SPACE SEPARATED STRINGS",
  22. }
  23. payload := url.Values{
  24. "username": {formData.Username},
  25. "password": {formData.Password},
  26. "grant_type": {formData.GrantType},
  27. "scope": {formData.Scope},
  28. }
  29. req, err := http.NewRequest("POST", endpoint, strings.NewReader(payload.Encode()))
  30. if err != nil {
  31. log.Printf("无法执行POST请求:\n%v", err)
  32. }
  33. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  34. req.Header.Add("Accept", "application/json")
  35. resp, err := http.DefaultClient.Do(req)
  36. if err != nil {
  37. log.Fatal(err)
  38. }
  39. defer resp.Body.Close()
  40. body, err := ioutil.ReadAll(resp.Body)
  41. if err != nil {
  42. log.Fatal(err)
  43. }
  44. log.Println(string(body))
  45. }
英文:

Implemented @RedBlue's suggestion:

  1. package main
  2. import (
  3. "io/ioutil"
  4. "log"
  5. "net/http"
  6. "strings"
  7. "net/url"
  8. )
  9. type Payload struct {
  10. Username string `json:"username"`
  11. Password string `json:"password"`
  12. GrantType string `json:"grant_type"`
  13. Scope string `json:"scope"`
  14. }
  15. func main() {
  16. const endpoint string = "https://api.io/v1/oauth/token"
  17. formData := &Payload{
  18. Username: "email",
  19. Password: "pass",
  20. GrantType: "password",
  21. Scope: "SPACE SEPARATED STRINGS",
  22. }
  23. payload := url.Values{
  24. "username": {formData.Username},
  25. "password": {formData.Password},
  26. "grant_type": {formData.GrantType},
  27. "scope": {formData.Scope},
  28. }
  29. req, err := http.NewRequest("POST", endpoint, strings.NewReader(payload.Encode()))
  30. if err != nil {
  31. log.Printf("Unable to perform POST request:\n%v", err)
  32. }
  33. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  34. req.Header.Add("Accept", "application/json")
  35. resp, err := http.DefaultClient.Do(req)
  36. if err != nil {
  37. log.Fatal(err)
  38. }
  39. defer resp.Body.Close()
  40. body, err := ioutil.ReadAll(resp.Body)
  41. if err != nil {
  42. log.Fatal(err)
  43. }
  44. log.Println(string(body))
  45. }

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:

确定