6

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.

7
  • I hope you're not ignoring errors like seen above. Commented Apr 17, 2013 at 15:29
  • 3
    No, they were nil - I just cut the code out for brevity. Commented Apr 17, 2013 at 15:31
  • 1
    I tried your example above on a web page which needs authentication and it worked fine. The moneyworks docs are worth a read, re HTTP/1.0. I don't see your auth parameters for your curl command so how is that working? Commented Apr 17, 2013 at 19:33
  • MoneyWorks allows an alternate URL scheme with the UN/PW embedded with the URL for direct cURL requests. ie. 1.2.3.4:6710/REST/user:[email protected]/params . Even so, when I leave the embeddd un/pw out of the cURL url I get "username/password required", which is to be expected. When using GO I get "404 Not Found". Something strange is going on, but at least I have it 100% working by passing the URL to cURL instead. I'll hack around with HTTP 1.0/1.1 and report back. Commented Apr 17, 2013 at 19:52
  • 3
    In the end, what matters is the bytes on the wire. I would use Wireshark to capture the bytes sent by both. If the critical difference isn't immediately apparent, I'd send variations (with any of http.Client, curl, or nc) until I can flip one thing and make either behavior happen at will. Then look for how to change that behavior in Go. Commented Apr 18, 2013 at 15:34

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

Comments

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.

1 Comment

Yeah, the MoneyWorks documentation states that their REST API works best with HTTP/1.0... obviously this is contradicted by the command-line cURL request working just fine with 1.1. Either way, the GO code doesn't work with 1.0 or 1.1. I've just decided to pass an OS call to cURL for now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.