On GoDaddy Hosting and PayPal IPN

...or to be more accurate: On GoDaddy and Proxy Servers

Let me start off by saying that I'm a big fan of GoDaddy. I've been one since I first heard of them (years ago, don't ask me when), and likely will be for years to come. This week, however, I had my first real run-in with their hosting services. Now, there's nothing really bad about the way they have them set up, but they have some annoyances (and, Mr Parsons, I *really* admire you and all you've achieved with GoDaddy, but the hosting support could really use a bit of spicing up. I understand that it's not financially sensible to offer dirt-cheap hosting and then cater to your millions of users' support issues, but IMHO there's an ethical necessity to do so anyway if you're willing to push the service so aggressively to users who're buying domains. You just can't offer them their dream-come-true perfect all-in-one solution... and then leave them hanging with no real tech support!)

Anyway, I'm ranting a bit. But to get to the point, one of the quirks of their hosting service is that they won't let you connect directly to external websites (documentation suggests that this used to be for HTTP and HTTPS requests, but I was able to connect directly to HTTP - my problems only started with HTTPS requests). Anyone who's got a web-crawler, SOAP application, RSS feeds, or (like I did) needs to integrate with an online payment provider knows what I mean. Now, it's really not a bad thing that they've done - it's really quite good (and smart) for everyone, at the end of the day. The problem is that it's not really documented so well - you've really got to know what you're looking for. Personally, I didn't. My troubles started when IPNs just wouldn't go through. After Googling a bit, I saw lots of others posting about some requirement for a proxy. "OK", I thought, "I can do proxy". So I went ahead, set up the proxy (http://proxy.shr.secureserver.net:3128 if you're that interested, though I'm sure you've seen that already, right?), and... got a 501 error? Method not implemented? So, what was I to do? I emailed support. While I waited 8 or so hours for them to answer me (the first time), I continued playing with all sort of proxy settings. I could go into it, but it's not really worth it (and I really don't like thinking about it - it was quite traumatizing, since I didn't have access to the error_log [they offer it, but only through the control panel, which doesn't do much for contractors like me who can't get to the control panel...]).

Now, I really didn't think that this should be such a big issue. There seemed to be some pretty straightforward code, for PHP at least ( I was using Perl - LWP, to be precise):

//curl_setopt ($CR, CURLOPT_HTTPPROXYTUNNEL, TRUE);
curl_setopt($CR, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
curl_setopt($CR, CURLOPT_PROXY,"http://proxy.shr.secureserver.net:3128");
curl_setopt($CR, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($CR, CURLOPT_URL, "https://www.paypal.com");
curl_setopt($CR, CURLOPT_TIMEOUT, 120);
$result = curl_exec( $CR );

But every which way the I tried to hack that proxy into LWP::UserAgent, I got nowhere.

Anyway, after 8 hours or so I got my response:

"Dear Sir/Madam,

Thank you for contacting Online Support. Please note that while Go Daddy Customer Service Representatives cannot debug your CGI Scripts or HTML website coding the information below should help you with your CGI enabled hosting account. There are many variables that could cause a page not to work correctly. As you troubleshoot the problem, bear in mind some of the more common causes of problems with scripts:

Now really? Besides the obvious question of how they thought I managed to get an error from their proxy server if I hadn't gotten all of that done, I suppose I couldn't complain. I mean, what was I expecting if not a pre-fabricated answer that has nothing to do with my original question (somehow that reminds me of Microsoft, but I can't put my finger on it). So, I wrote them back, trying to explain using simple words and short sentences that they didn't address the issue in any way shape or form, and went back to trying to sort it out on my own ( as I had a long time until I heard back).

I won't go into the painful details of the next few emails. Suffice it to say that they were more nice canned answers to questions that I wasn't asking. But then, a few days later, I got an interesting one:

"Dear Sir/Madam,

Thank you for contacting Online Support. Please be advised that HTTPS connections will need to be made proxy aware. The proxy server IP address is 64.202.165.130 with connections made on port 443 (port 3128 would be for HTTP connections). I hope that this information is helpful in solving your connection problem.

If you continue to experience an error, please provide us with the URL where you have this script located along with what exactly you are attempting to accomplish on your site.

Please let us know if we can help you in any other way."

Wow! That seemed to actually reflect my issue. I was impressed! They even seemed to imply that they'd look at my code! (Actually, the only thing wrong about it is that it turns out to be misleading (and, unfortunately, wrong), but we'll get to that.)

I wasn't going to waste this golden egg, so I set to making a nice script that demonstrated every use of the proxy I could think of. It was only while doing this (and, by extension, staring at that damned proxy error) that it hit me. Method not implemented.... Method not implemented... HTTP proxy... Method not implemented... HTTP... Eureka! I'd been staring it the face, but ignoring it, because it was always commented out. Apparantly CURL works without it. See, I'd already realized that the 443 was a red herring, and somehow the subconciously implied HTTPS was, too. The proxy only responded on 3128, and only spoke HTTP. "Method not implemented" makes sense because when talking HTTPS to an HTTP server, the request line is encrypted, so squid isn't grokking it. Now really, you should be ashamed of yourself for not having seen that sooner! I didn't, because like I said, it was always there but commented out: //curl_setopt ($CR, CURLOPT_HTTPPROXYTUNNEL, TRUE);

You can't GET in HTTPS with an HTTP proxy. You need to CONNECT. LWP::UserAgent doesn't CONNECT, but Crypt::SSLeay does... And therein lies the answer.

The solution is then to use Crypt::SSLeay's proxy ability and NOT LWP's. This is all mentioned in the Crypt::SSLeay manpage, by the way. There's a whole section devoted to it. The solution is then to drop all of the LWP proxy stuff (including $ua->proxy_env; That'll just kill it all!) and to use Crypt::SSLeay's proxy simply by setting
$ENV{HTTPS_PROXY}="http://proxy.shr.secureserver.net:3128";
anywhere at all in the code (well, anywhere before LWP does the request, obviously). For those reading this that need Basic Auth for their proxy, you can define $ENV{HTTPS_PROXY_USERNAME} and $ENV{HTTPS_PROXY_PASSWORD} to handle that, too.

Bottom line is that GoDaddy should really invest in better documentation for their services - it's painfully obvious if you ignore the obvious ( there's an oxymoron for you!) but it could definately be spelled out better.

I hope I've saved some poor person from the hell I've gone through making heads or tails of this :-)