HttpSocket Instead of cURL in CakePHP Apps

Posted by Matt on Mon, Feb 16 2009

There are a few new Bakery articles lately that use cURL for remote calls (see here and here), rather then Cake's HttpSocket lib. This is probably because HttpSocket doesn't have a mention in the CookBook (yet :)).

Here's a quick primer on using HttpSocket as an alternative. I'll re-write the code from the TwitterMail article as an example.

First, their original code:

$curl_twitter = curl_init();
curl_setopt($curl_twitter, CURLOPT_URL, 'http://twitter.com/account/verify_credentials.json');
curl_setopt($curl_twitter, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl_twitter, CURLOPT_HEADER, false);
curl_setopt($curl_twitter, CURLOPT_USERPWD, $this->data[$this->name]['twitter_username']
                                            .":".$this->data[$this->name]['twitter_password']);
curl_setopt($curl_twitter, CURLOPT_POST, true);
curl_setopt($curl_twitter, CURLOPT_RETURNTRANSFER, true);
$curl_result = curl_exec($curl_twitter);
curl_close($curl_twitter);

Now using HttpSocket instead:

App::import('Core', 'HttpSocket');
$HttpSocket = new HttpSocket();
$request = array('auth' => array('user' => $this->data[$this->name]['twitter_username'],
                                 'pass' => $this->data[$this->name]['twitter_password'],
                                 'method' => 'Basic'),
                 'uri' => 'http://twitter.com/account/verify_credentials.json');
$result = $HttpSocket->request($request);

I explicitly set the auth method to "Basic" here. This is because the default auth method is "basic" - notice the lowercase "b". Twitter doesn't like this. This is fixed in the trunk version of Cake, but if you're using the latest release (8004), you'll need to set it manually.

There you go. Nine cURL lines becomes four lines of Cake code. In addition the dependency on the cURL lib is removed as HttpSocket uses PHP's fsockopen. Cake's HttpSocket doesn't have all the features of cURL, but it's certainly handles most web services with no problem.

Posted in CakePHP

15 Comments

LennieZ said on Feb 16, 2009
Thanks! I didn't know this before.
Sometimes I saw this HttpSocket but I thought Curl was better =)

But yes, this is much more easier and in stead of 9 lines it's 4 now.

Thanks for the tip.

LennieZ
tg2345 said on Feb 16, 2009
Thanks was doing stuff in cURL without any knowledge of HttpSocket.
elvy said on Feb 16, 2009
awesome - thanks
Thiago Belem said on Feb 17, 2009
Fantastic! :D

Certainly I'll assume this way.
Marcel Esser said on Feb 17, 2009
Why would I prefer a PHP class over a C extension? Especially when that C extension has already been tested by thousands.
Matt said on Feb 17, 2009
Off the top of my head: No external dependencies, easier syntax. Like I mentioned in the post the HttpSocket class is really just a wrapper for PHP's native fsockopen.

If you're going to use Cake (or any other framework) it makes sense to take advantage of anything that makes you're development life easier.
Manny said on Feb 17, 2009
You said, "Cake’s HttpSocket doesn’t have all the features of cURL" So in which situations would you use CURL over HttpSocket?

I also remember that CURL is faster. Could be wrong!

BTW, you could also create a request wrapper for CURL code instead of repeating CURL stuff.
Matt said on Feb 17, 2009
I knew that line would come back to bite me. Looking at cURL's options it would seem that there is support for anything you could want (binary, proxies, FTP, SSL, speed, retry...).

The options for HttpSocket don't cover nearly all those areas. I'm sure someone will counter that you can use the "raw" option and pass it whatever you want, which is probably true.

In general I would try to use HttpSocket, since it works for 99% of the scenarios and if I hit a something it doesn't work for I'd switch to cURL. Or a wrapper to cURL as you mentioned. I'm sure there's one in the Bakery.

I have no clue on the speed difference, but I would guess it's minimal especially compared to the actual remote call.
Manny said on Feb 17, 2009
Thanks Matt, I wasn't trying to put you on the spot. I was hoping to figure when / when not to use HttpSocket instead digging through the code!

I'll test out HttpSocket ;)
Manny said on Feb 18, 2009
Hey Matt,

Finally found time to hack with this. Would you happen to know how HttpSocket handles HTTP result codes such as 404? Can the code be retrieved? CURL has a timeout option, CURLOPT_TIMEOUT. I checked Cake's API and didn't see anything. The reason is that Twitter does have a reputation for being down!

Thanks
Matt said on Feb 18, 2009
You can set the timeout by passing array('timeout' => 10) to the HttpSocket constructor. Check out the $config var for the full array of options.

404 is different. That means the server responded, but didn't find the page you wanted. You can check that in:
$HttpSocket->response['status']['code']
Manny said on Feb 19, 2009
Matt, you're the man! I'm a convert. I'm going to try and polish off a twitter model on the weekend.
Jason Leveille said on Feb 18, 2009
Here is another option that you might find interesting ... outside of a CakePHP context. Though, I have used this wrapper in CakePHP projects in the past:

http://github.com/shuber/curl/tree/master
mscdex said on Feb 19, 2009
There's also a CakePHP cURL Model that acts as a wrapper that supposedly works with Cake 1.x.x: http://bakery.cakephp.org/articles/view/curl-model
Angel S. Moreno said on Jun 17, 2010
AFAIK, HttpSocket also lacks proxy options. The CakePHP cURL Model might just be the best of both worlds.

Add new comment