You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go构造HTTP POST请求时如何将查询参数值写入请求体

问题根因
  • 调用http.NewRequest时传入的请求体是即时生成的空字符串:此时url.Values还未添加任何参数,q.Encode()执行结果为空,后续修改q不会同步更新已经生成的请求体内容。
  • 原代码查询参数获取逻辑错误:req是你新构造的发往第三方认证接口的请求,本身不携带前端传入的查询参数,应该从当前处理的请求对象r中读取查询参数。
修正方案

优先调整代码执行顺序:先完成所有参数填充,再编码生成请求体,是最清晰易维护的实现方式。
修正后的完整代码如下:

func Fetch(w http.ResponseWriter, r *http.Request) {
    client := &http.Client{}

    q := url.Values{}
    // 先填充所有参数
    q.Add("grant_type", "authorization_code")
    q.Add("id", os.Getenv("ID"))
    q.Add("secret", os.Getenv("SECRET"))
    q.Add("redirect_uri", "https://callback.com")
    // 从当前接收的请求r中获取查询参数,包括你需要的code参数
    q.Add("code", r.URL.Query().Get("code"))
    q.Add("query-param", r.URL.Query().Get("query-param"))

    // 所有参数填充完成后,再编码生成请求体构造请求
    req, err := http.NewRequest("POST", "https://auth.truelayer-sandbox.com/connect/token", strings.NewReader(q.Encode()))
    if err != nil {
        log.Print(err)
        fmt.Println("Error was not equal to nil at first stage.")
        os.Exit(1)
    }

    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Error sending request to server")
        os.Exit(1)
    }
    defer resp.Body.Close() // 避免资源泄漏

    respBody, _ := ioutil.ReadAll(resp.Body)
    w.WriteHeader(resp.StatusCode)
    w.Write(respBody)
}

可选兼容方案

如果存在业务逻辑必须先构造请求再填充参数的场景,可以在参数填充完成后,手动替换请求的Body属性并设置ContentLength:

// 原有构造请求逻辑不变,初始请求体设为nil
q := url.Values{}
req, err := http.NewRequest("POST", "https://auth.truelayer-sandbox.com/connect/token", nil)
// 填充参数逻辑不变
q.Add("grant_type", "authorization_code")
// ...其他参数添加逻辑
// 手动设置请求体
req.Body = io.NopCloser(strings.NewReader(q.Encode()))
req.ContentLength = int64(len(q.Encode()))

内容的提问来源于stack exchange,提问作者Jon Nicholson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 01:06:05