尝试在使用Go/Gin的应用程序中进行HTTP请求,并返回该请求的结果。

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

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 &quot; 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{&quot;error&quot;: err.Error()})
    return
}
c.Data(200, &quot;application/json&quot;, respbody) // &lt;-- note this line

You can also copy from one response to the other:

defer res.Body.Close()
c.DataFromReader(200, res.ContentLength, &quot;application/json&quot;, res.Body, nil)

huangapple
  • 本文由 发表于 2021年10月18日 09:49:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/69609971.html
匿名

发表评论

匿名网友

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

确定