【问题标题】:Golang HTTP GET request returning 404Golang HTTP GET 请求返回 404
【发布时间】:2013-04-17 15:09:24
【问题描述】:

我正在尝试使用 BasicAuth 执行简单的 HTTP 获取。问题是响应不断返回“404”,即使我可以将 URL 复制并粘贴到命令行 cURL 请求中并且它工作正常:

const url string = "http://1.2.3.4:6710/REST/command"
const username string = "..."
const password string = "..."

fmt.Printf("\n%v\n", url)

client := &http.Client{}

req, _ := http.NewRequest("GET", url, nil)
req.SetBasicAuth(username, password)
req.Proto = "HTTP/1.0"
req.ProtoMinor = 0

resp, _ := client.Do(req)

fmt.Printf("\n%v\n", resp)

defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)   

fmt.Printf("\n%v\n\n", string(body))

所以你可以看到我正在立即打印出我的url - 这是同一行文本,如果我复制到命令行 cURL 请求中,一切正常。

我的请求响应是

&{404 Not Found 404 HTTP/1.0 1 0 map[Pragma:[no-cache] Date:[Wed, 17 Apr 2013 15:01:33 GMT] Connection:[close] Server:[MoneyWorks_Datacentre/6.1.3 Win-x86 REST/6.1.3] Cache-Control:[no-store, no-cache, must-revalidate] Expires:[Wed, 17 Apr 2013 15:01:33 GMT]] 0xf8400e3920 -1 [] true map[] 0xf8400aa000}

golang 的 HTTP 函数有什么独特之处与 cURL 处理如此简单的请求的方式不同吗?

编辑:我通过将 URL 传递给 exec.Command("curl", url).Output() 使其工作。显然这不是我希望的原生解决方案,但它现在可以工作。

【问题讨论】:

  • 我希望你没有忽略上面看到的错误。
  • 不,他们是nil - 为了简洁起见,我只是把代码删掉了。
  • 我在需要身份验证的网页上尝试了上面的示例,并且效果很好。 The moneyworks docs 值得一读,重新 HTTP/1.0。我没有看到你的 curl 命令的身份验证参数,所以它是如何工作的?
  • MoneyWorks 允许替代 URL 方案,其中 UN/PW 嵌入直接 cURL 请求的 URL。 IE。 1.2.3.4:6710/REST/user:pass@document.mwd6/params。即便如此,当我将 embeddd un/pw 留在 cURL url 之外时,我会得到“需要用户名/密码”,这是意料之中的。使用 GO 时,我得到“404 Not Found”。发生了一些奇怪的事情,但至少我通过将 URL 传递给 cURL 来使其 100% 正常工作。我会修改 HTTP 1.0/1.1 并报告。
  • 最后,重要的是线路上的字节。我会使用 Wireshark 来捕获两者发送的字节。如果关键差异没有立即显现,我会发送变体(使用http.Clientcurlnc 中的任何一个),直到我可以翻转一件事并随意发生任何一种行为。然后寻找如何在 Go 中改变这种行为。

标签: curl get go


【解决方案1】:

问题与 Unicode 相关。我的命令中有一个 %2F(未显示在我的原始问题中),Go 正在转换为 /,应该保留为 %2F(cURL 正确地将其保留为 %2F)。将%2F 更改为%252F 解决了这个问题。

似乎在创建新的 HTTP 请求时,Go 会将您的 unicode 解析回纯文本,因此如果您提交给 HTTP 请求初始化程序的 URL 中有 %3D,它会将其转换为 =。我认为一个明显的解决方案是将%253D 放入URL,但显然Go 中有一个错误会将%3D 转换为=,但不会将%25 转换为%。我不得不使用不透明 URL 请求 (request.Url.Opaque) 来解决这个问题。

【讨论】:

    【解决方案2】:

    你说 curl 命令可以正常工作,但如果你有最新的 curl(我的是 7.22.0)。请求是这样的:

    curl url --verbose

    GET / HTTP/1.1

    用户代理:curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3

    主机:myhost.com

    接受:/

    但是你正在设置req.Proto = "HTTP/1.0"。好像不太对。

    【讨论】:

    • 是的,MoneyWorks 文档指出他们的 REST API 最适用于 HTTP/1.0... 显然这与命令行 cURL 请求在 1.1 中运行良好相矛盾。无论哪种方式,GO 代码都不适用于 1.0 或 1.1。我刚刚决定暂时将操作系统调用传递给 cURL。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    相关资源
    最近更新 更多