【问题标题】:Golang POST request to API returns 400, while the same request with e. g. Postman returns 200Golang 对 API 的 POST 请求返回 400,而与 e 相同的请求。 G。邮递员返回 200
【发布时间】:2018-03-03 16:33:19
【问题描述】:

在我的 Go 应用程序中,我使用了一个 Web API,它接受一个 POST 请求并在成功时返回一个令牌。

网址如下:“https://accounts.zoho.com/apiauthtoken/nb/create?SCOPE=xxxx&EMAIL_ID=xxxx&PASSWORD=xxxx

如果我在 Postman 或任何其他工具中发送它,我会得到带有预期正文的状态代码 200,但在我的 go 代码中,相同的请求返回错误代码 400。

url := "https://accounts.zoho.com/apiauthtoken/nb/create?SCOPE=xxxx&EMAIL_ID=xxxx&PASSWORD=xxxx"

req, err := http.NewRequest("POST", url, nil)
log.Println(err)

res, err := client.Do(req)
log.Println(err)

defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
log.Println(err)

fmt.Println(res)
fmt.Println(string(body))

所有错误都是 nil,但 res 结构包含 400 Bad Request 并且(正文的)最后一个输出是空的。

输出:

&{400 Bad Request 400 HTTP/1.1 1 1 map[Date:[Sat, 03 Mar 2018 16:48:35 GMT] Connection:[keep-alive] Set-Cookie:[a8c61fa0dc=5f224f2ab9d067cfce10fd0b7fae48bf; Path=/; Secure; HttpOnly] Server:[ZGS]] 0xc04225a080 -1 [chunked] false false map[] 0xc042034a00 0xc0421bc370}

我会很感激任何帮助,因为我不知道这个问题来自哪里。

【问题讨论】:

  • 我在使用微服务时也遇到了同样的问题。在终端中使用 go run 运行程序时,您可以打印应该在控制台上得到的错误输出吗
  • 我更新了我的问题并添加了输出,但正如我所说,错误为零,响应“对象”包含 400。

标签: api post go request


【解决方案1】:

Url 编码的参数应该在正文参数中提供,而不是作为查询字符串。所以这也可能是一个问题。在实现 io.Reader 的正文中设置您的参数。

func NewRequest(method, url string, body io.Reader) (*Request, error)

在使用 Client.Do 发送请求之前,在请求中设置标头 Content-Type。

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

因为邮递员足够聪明,可以为您设置标题。这就是为什么没有错误。 整个代码变成了

package main

import (
    "log"
    "net/http"
    "net/url"
    "io/ioutil"
    "strings"
)
func main(){

    url := "https://accounts.zoho.com/apiauthtoken/nb/create"

    var data url.Values{}
    data.Set("SCOPE","xxxx")
    data.Add("EMAIL","xxxx")
    data.Add("PASSWORD","xxxx")
    req, err := http.NewRequest("POST", url, strings.NewReader(data.Encode()))
    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

    log.Println(err)

    res, err := client.Do(req)
    log.Println(err)

    defer res.Body.Close()
    body, err := ioutil.ReadAll(res.Body)
    log.Println(err)

    fmt.Println(res)
    fmt.Println(string(body))

}

【讨论】:

  • 我之前已经尝试过设置 Content-Type,但我不知道您需要额外传递 url 值。谢谢
  • url.Values{} 实际上是一个类型map[string][]string,它是一个创建的Type
  • 您知道为什么 API 仍然无法使用您的方法发送或接收参数吗? API 发送的消息与您根本不提供任何参数时发送的消息完全相同。如果任何参数被损坏,它会返回一个特定的错误消息,所以情况并非如此
  • 您是否会显示您收到的错误消息以及您是否能够获取发布的参数
  • 这是我从 API 获得的结果(我希望它将 RESULT 设置为 TRUE,而不是 CAUSE 返回一个 TOKEN:# #Tue Mar 06 12:20:41 PST 2018 CAUSE=null RESULT=FALSE 我不知道您所说的“get发布的参数”。
【解决方案2】:

我遇到了类似的问题。 401 的原因仅仅意味着无效的授权令牌。后来我注意到 Postman 执行 Pre-request script 每次都会更新标题。您可以在 golang 中提取相同的预请求脚本代码,并且它可以工作。

【讨论】:

    【解决方案3】:

    这里有同样的问题,尝试在 url 中使用一些 QUERY 参数发出 POST 请求,这在 Postman 中工作正常,但在 go debug 中总是使用所有相同的参数(查询参数、post body、headers 和 MD5 符号)得到 Http 400

    timeStr := time.Now().Format("2006-01-02 15:04:05")
    serverUrlAll = serverUrlAll + "?token="+token+"&provider="+provide+"&timestamp="+timeStr+"&signature="+signature
    contentBody := strings.NewReader(signString)
    request, err := http.NewRequest("POST",serverUrlAll , contentBody)
    if err != nil {
        return nil, err
    }
    request.Header.Set("Content-Type", "application/json")
    

    终于发现查询网址中的空白会导致错误,删除空白,它适用于我的情况。

    【讨论】:

      猜你喜欢
      • 2019-05-23
      • 1970-01-01
      • 2022-11-02
      • 2021-11-20
      • 1970-01-01
      • 2017-05-16
      • 1970-01-01
      • 2015-09-27
      • 1970-01-01
      相关资源
      最近更新 更多