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
相关产品推荐
相关产品推荐

