Golang的HTTP GET请求返回404

huangapple go评论75阅读模式
英文:

Golang HTTP GET request returning 404

问题

我正在尝试使用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()来使其工作。显然,这不是我希望的本地解决方案,但现在它可以工作了。

英文:

I am trying to execute a simple HTTP get with BasicAuth. The problem is that the response keeps coming back "404", even though I can copy and paste the URL into a command-line cURL request and it works fine:

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))

So you can see that I am printing out my url immediately - this is the same line of text that if I copy into a command-line cURL request, all works perfectly.

My request response is

&{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}

Is there anything unique to golang's HTTP functions that differ from the way cURL would handle such a simple request?

EDIT: I have it working by passing the URL to exec.Command("curl", url).Output(). Obviously this is not the native solution I am hoping for but it works for now.

答案1

得分: 3

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

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

英文:

The issue was unicode-related. There was a %2F in my command (not displayed in my original question) that Go was converting to / that should have been left as %2F (cURL was properly leaving it as %2F). Changing the %2F to %252F fixed the issue.

It also appears that when creating a new HTTP request Go will parse your unicode back to plain text, so if you have %3D in the URL you submit to the HTTP request initializer it will convert it to =. I thought an obvious solution would be to put %253D into the URL but apparently there is a bug in Go that will convert %3D to = but NOT %25 to %. I had to use the Opaque URL request (request.Url.Opaque) to get around this.

答案2

得分: 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"。看起来不对。

英文:

You say the curl command just works but if you have the latest curl(mine is 7.22.0). The request would be something like this:

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: /

But you are setting req.Proto = "HTTP/1.0". Doesn't seem right.

huangapple
  • 本文由 发表于 2013年4月17日 23:09:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/16063724.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定