英文:
Golang Struct as Payload for POST Request
问题
新手学习golang。我正在尝试向身份验证端点发出POST请求,以获取用于进一步身份验证的令牌。目前我得到的错误是missing "credentials"
。我已经用Python编写了相同的逻辑,所以我知道我尝试做的是系统所期望的。
问题是-我是否正确地将AUTH结构编组为JSON,并适当地将其添加到POST请求中?由于API甚至没有在JSON中看到credentials
键,我认为我一定做错了什么。任何帮助都可以。
英文:
New to golang. I'm trying to make a POST request to an auth endpoint to get back a token for authing further requests. Currently the error I'm getting is missing "credentials"
. I've written the same logic in Python so I know what I am trying to do is what the system is expecting.
package main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/cookiejar"
"os"
)
type Auth struct {
Method string `json:"credentials"`
Email string `json:"email"`
Password string `json:"password"`
Mfa string `json:"mfa_token"`
}
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter Email: ")
e, _ := reader.ReadString('\n')
fmt.Print("Enter Password: ")
p, _ := reader.ReadString('\n')
fmt.Print("Enter 2FA Token: ")
authy, _ := reader.ReadString('\n')
auth := Auth{"manual", e, p, authy}
j, _ := json.Marshal(auth)
jar, _ := cookiejar.New(nil)
client := &http.Client{
Jar: jar,
}
req, err := http.NewRequest("POST", "https://internaltool.com/v3/sessions", bytes.NewBuffer(j))
if err != nil {
log.Fatal(err)
}
req.Header.Add("Accept-Encoding", "gzip, deflate, br")
res, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
s := string(body)
if res.StatusCode == 400 {
fmt.Println("Bad Credentials")
fmt.Println(s)
return
}
}
The question is - am I properly marshalling the AUTH struct into JSON and adding it appropriately to the POST request? As the API is not even seeing the credentials
key in the JSON I think I must be doing something wrong. Anything helps.
答案1
得分: 13
这是一个使用json.Marshal
的最小可行示例,将结构体转换为JSON对象,并在POST请求的上下文中使用。
Go的标准库非常出色,没有必要引入外部依赖来完成这样的琐事。
func TestPostRequest(t *testing.T) {
// 创建一个Person的新实例
person := Person{
Name: "Ryan Alex Martin",
Age: 27,
}
// 在发起请求之前将其编组为JSON
personJSON, err := json.Marshal(person)
// 使用编组后的JSON作为POST请求的主体进行请求
resp, err := http.Post("https://httpbin.org/anything", "application/json",
bytes.NewBuffer(personJSON))
if err != nil {
t.Error("无法向httpbin发起POST请求")
}
// 就是这样!
// 但为了保险起见,让我们查看一下响应主体。
body, err := ioutil.ReadAll(resp.Body)
var result PersonResponse
err = json.Unmarshal([]byte(body), &result)
if err != nil {
t.Error("从请求中解组数据时出错。")
}
if result.NestedPerson.Name != "Ryan Alex Martin" {
t.Error("从服务器返回的名称字段不正确或为空:", result.NestedPerson.Name)
}
fmt.Println("来自服务器的响应:", result.NestedPerson.Name)
fmt.Println("来自服务器的响应:", result.NestedPerson.Age)
}
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
// NestedPerson是响应的'json'字段,即我们最初发送到httpbin的Nested Person{}
type PersonResponse struct {
NestedPerson Person `json:"json"` // 在'json'字段中的嵌套Person{}
}
英文:
Here's a minimum viable example of using json.Marshal
to convert a Struct to a JSON object in the context of a POST request.
Go's standard libraries are fantastic, there is no need to pull in external dependencies to do such a mundane thing.
func TestPostRequest(t *testing.T) {
// Create a new instance of Person
person := Person{
Name: "Ryan Alex Martin",
Age: 27,
}
// Marshal it into JSON prior to requesting
personJSON, err := json.Marshal(person)
// Make request with marshalled JSON as the POST body
resp, err := http.Post("https://httpbin.org/anything", "application/json",
bytes.NewBuffer(personJSON))
if err != nil {
t.Error("Could not make POST request to httpbin")
}
// That's it!
// But for good measure, let's look at the response body.
body, err := ioutil.ReadAll(resp.Body)
var result PersonResponse
err = json.Unmarshal([]byte(body), &result)
if err != nil {
t.Error("Error unmarshaling data from request.")
}
if result.NestedPerson.Name != "Ryan Alex Martin" {
t.Error("Incorrect or nil name field returned from server: ", result.NestedPerson.Name)
}
fmt.Println("Response from server:", result.NestedPerson.Name)
fmt.Println("Response from server:", result.NestedPerson.Age)
}
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
// NestedPerson is the 'json' field of the response, what we originally sent to httpbin
type PersonResponse struct {
NestedPerson Person `json:"json"` // Nested Person{} in 'json' field
}
答案2
得分: 0
作为一个相对较低级的抽象,强烈推荐使用gorequest
(https://github.com/parnurzeal/gorequest)作为http.Client
的替代方案。
可以以任何类型发布头部、查询和正文,这更像是我们在Python中经常做的事情。
英文:
As http.Client
is relatively a low-level abstraction, gorequest
(https://github.com/parnurzeal/gorequest) as an alternative is strongly recommended.
headers, queries, and body can be posted in any type, which is a bit more like what we often do in Python.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论