英文:
Trying to make a HTTP request and return the result of that request in an app that uses go/gin
问题
我刚刚开始学习Go语言,想知道如何使用Gin创建的API进行HTTP请求并返回请求结果。
以下是返回另一个请求结果的端点的代码:
func ProvideAccessToken(c *gin.Context) {
body := bindings.RequestAccessTokenBody{}
err := c.ShouldBind(&body)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
log.Println(err)
return
}
if body.Code == "" || body.GrantType == "" || body.RedirectURI == "" {
c.String(http.StatusBadRequest, "Bad Request")
return
}
res, err := helpers.ExchangeCodeForToken(body.GrantType, body.RedirectURI, body.Code)
if err != nil {
c.JSON(res.StatusCode, gin.H{"error": err.Error()})
return
}
defer res.Body.Close()
c.Header("Content-Type", "application/json")
c.JSON(200, res.Body)
}
以下是执行HTTP请求的函数:
func ExchangeCodeForToken(grantType string, redirectUri string, code string) (*http.Response, error) {
authToken := "Basic " + encodeClientSecretAndId()
body := url.Values{}
body.Set("grant_type", grantType)
body.Set("redirect_uri", redirectUri)
body.Set("code", code)
encodedBody := body.Encode()
client := &http.Client{}
r, _ := http.NewRequest(http.MethodPost, tokenUrl, strings.NewReader(encodedBody))
r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
r.Header.Add("Authorization", authToken)
res, err := client.Do(r)
return res, err
}
当我使用Postman进行请求时,响应只是一个空的JSON,如{}
。
当我将ProvideAccessToken
函数的结尾更改为以下内容时:
defer res.Body.Close()
respbody, err := ioutil.ReadAll(res.Body)
if err != nil {
c.JSON(res.StatusCode, gin.H{"error": err.Error()})
return
}
c.Header("Content-Type", "application/json")
c.JSON(200, string(respbody))
我得到的结果是"{\"error\":\"invalid_grant\",\"error_description\":\"Authorization code expired\"}"
,这是正确的,但格式有些奇怪。我只想返回其他API返回的内容。
英文:
I just picked up Go yesterday and I was wondering how I can make an HTTP request and return the result of that request with my API made with Gin.
This is the code for the endpoint that returns the result of another request
func ProvideAccessToken(c *gin.Context) {
body := bindings.RequestAccessTokenBody{}
err := c.ShouldBind(&body)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
log.Println(err)
return
}
if body.Code == "" || body.GrantType == "" || body.RedirectURI == "" {
c.String(http.StatusBadRequest, "Bad Request")
return
}
res, err := helpers.ExchangeCodeForToken(body.GrantType, body.RedirectURI, body.Code)
if err != nil {
c.JSON(res.StatusCode, gin.H{"error": err.Error()})
return
}
defer res.Body.Close()
c.Header("Content-Type", "application/json")
c.JSON(200, res.Body)
}
This is the function that makes the HTTP request
func ExchangeCodeForToken(grantType string, redirectUri string, code string) (*http.Response, error) {
authToken := "Basic " + encodeClientSecretAndId()
body := url.Values{}
body.Set("grant_type", grantType)
body.Set("redirect_uri", redirectUri)
body.Set("code", code)
encodedBody := body.Encode()
client := &http.Client{}
r, _ := http.NewRequest(http.MethodPost, tokenUrl, strings.NewReader(encodedBody))
r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
r.Header.Add("Authorization", authToken)
res, err := client.Do(r)
return res, err
}
When I use postman to make a request, the response is just an empty json like so{}
.
When change the end of my ProvideAccessToken
function to be
defer res.Body.Close()
respbody, err := ioutil.ReadAll(res.Body)
if err != nil {
c.JSON(res.StatusCode, gin.H{"error": err.Error()})
return
}
c.Header("Content-Type", "application/json")
c.JSON(200, string(respbody))
I get this as my result "{\"error\":\"invalid_grant\",\"error_description\":\"Authorization code expired\"}"
, which is correct but it has the weird formatting. I just want to return exactly what the other API returns.
答案1
得分: 3
程序的第一个版本将响应体值编码为JSON。响应是{},因为响应体中没有导出字段。这不是你想要的。
程序的第二个版本将JSON响应编码为JSON。奇怪的格式是对原始JSON中的"
进行转义。
将数据原样写入响应。这是对程序第二个版本的修改:
defer res.Body.Close()
respbody, err := ioutil.ReadAll(res.Body)
if err != nil {
c.JSON(res.StatusCode, gin.H{"error": err.Error()})
return
}
c.Data(200, "application/json", respbody) // <-- 注意这一行
你也可以从一个响应复制到另一个响应:
defer res.Body.Close()
c.DataFromReader(200, res.ContentLength, "application/json", res.Body, nil)
英文:
The first version of the program encodes the response body value as JSON. The response is {} because there are no exported fields in the response body. It's not what you want.
The second version of the program encodes the JSON response as a JSON. The weird formatting is the escaping of the "
in the original JSON.
Write the data as is to the response. Here's a modification to the second version of the program:
defer res.Body.Close()
respbody, err := ioutil.ReadAll(res.Body)
if err != nil {
c.JSON(res.StatusCode, gin.H{"error": err.Error()})
return
}
c.Data(200, "application/json", respbody) // <-- note this line
You can also copy from one response to the other:
defer res.Body.Close()
c.DataFromReader(200, res.ContentLength, "application/json", res.Body, nil)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论