Golang HTTP GET请求返回404

6

我试图使用BasicAuth执行一个简单的HTTP get请求。问题是响应一直返回"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(),我已经让它工作了。显然,这不是我希望得到的本地解决方案,但现在它能用了。

我希望你不要忽略像上面看到的错误。 - zzzz
3
不,它们是“nil” - 我只是为了简洁而剪切了代码。 - Darrrrrren
1
我在需要身份验证的网页上尝试了您上面的示例,它运行良好。Moneyworks文档值得一读,特别是关于HTTP/1.0的部分。我没有看到您curl命令的身份验证参数,那么它是如何工作的呢? - Nick Craig-Wood
MoneyWorks允许使用备用URL方案,其中UN/PW嵌入URL以进行直接cURL请求。例如:1.2.3.4:6710/REST/user:pass@document.mwd6/params。即便如此,当我在cURL URL中省略嵌入的UN/PW时,会出现“需要用户名/密码”的提示,这是可以预料的。当使用GO时,我得到了“404未找到”的错误。有些奇怪的事情正在发生,但至少我通过将URL传递给cURL来使其100%工作。我将尝试使用HTTP 1.0/1.1并报告结果。 - Darrrrrren
3
最终重要的是传输的字节流。我会使用Wireshark来捕获两者发送的字节流。如果关键区别不明显,我会发送变化版本(使用http.Client, curl, 或 nc中的任何一个)直到能够轻易地使其中之一的行为发生改变。然后寻找如何在Go语言中更改该行为。 - Scott Lamb
显示剩余2条评论
2个回答

3
问题是与 Unicode 相关的。我的命令中有一个 %2F(在我的原始问题中未显示),Go 将其转换为应该保留为 %2F/(cURL 正确地将其保留为 %2F)。将 %2F 改为 %252F 可以解决问题。
此外,创建新的 HTTP 请求时,Go 会将您的 Unicode 解析回纯文本,因此如果您在提交给 HTTP 请求初始化器的 URL 中有 %3D,它将转换为 =。我认为一个显而易见的解决方案是在 URL 中放置 %253D,但显然 Go 中存在一个错误,它将 %3D 转换为 =,但不会将 %25 转换为 %。我不得不使用 Opaque URL 请求(request.Url.Opaque)来解决这个问题。

0

你说curl命令只是起作用,但如果你有最新的curl(我的是7.22.0),请求应该像这样:

curl url --verbose

GET / HTTP/1.1

User-Agent: 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

Host: myhost.com

Accept: /

但你正在设置req.Proto = "HTTP/1.0"。看起来不对。


是的,MoneyWorks文档说明他们的REST API最适用于HTTP/1.0...显然这与命令行cURL请求在1.1上正常工作相矛盾。无论如何,GO代码在1.0或1.1上都无法工作。我决定暂时通过OS调用cURL来解决问题。 - Darrrrrren

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接