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("
%v
", 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("
%v
", resp)
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Printf("
%v
", 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.
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.
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.