Making HTTP requests in PHP is not difficult, and a variety of methods exists: using fopen(), using cURL extension, using file streams with fsockopen() and fwrite() for instance. The problem is: depending on server setup, this might or might not work on another server. The good new is: once again, WordPress has a no-brainer API that makes it dead easy and compatible with all environments.
Introducing PHP class WP_Http
WordPress, since version 2.7 and thanks to the extreme coding leetness of Jacob Santos, has a nifty class that sits in your wp-includes directory, in file http.php: WP_Http
WordPress 3.x update: you now need to explicitly include the class if you intend to use it, that is start by adding the following lines:
- if( !class_exists( 'WP_Http' ) )
- include_once( ABSPATH . WPINC. '/class-http.php' );
The power and beauty of this class is that, depending on what's available on the server, it will pick up the best method to perform HTTP request. Don't bother checking for the presence of HTTP extension, fopen() behavior, existence of curl_init(), as this class will do all this for you.
Basically, all the code you need to type is, more or less:
- $request = new WP_Http;
- $result = $request->request( 'http://some.url.you-need.to-fetch' );
Variable $result will be an array, containing the following items:
- 'headers': an array of response headers, such as "x-powered-by" => "PHP/5.2.1"
- 'body': the response string sent by the server, as you would see it with you web browser
- 'response': an array of HTTP response codes. Typically, you'll want to have array('code'=>200, 'message'=>'OK')
- 'cookies': an array of cookie information
Now, let's see a few more complex examples and real world situations
Basic stuff: a simple GET request
Let's say your next plugin needs to poll Twitter's search service for latest tweets about rabbits. It's no more code than:
- $url = 'http://search.twitter.com/search.json?q=rabbits';
- $request = new WP_Http;
- $result = $request->request( $url );
- $json = $result['body'];
This is all you need for a JSON encoded string containing what you're looking for.
Slightly more advanced: a standard POST request
If you need to pass some parameters, say nick= 'ozh' and mood='happy', using the POST method, here is how you modify the request:
- $body = array(
- 'nick' => 'ozh',
- 'mood' => 'happy'
- );
- $url = 'http://your.api.url/';
- $request = new WP_Http;
- $result = $request->request( $url, array( 'method' => 'POST', 'body' => $body) );
- // test $result['response'] and if OK do something with $result['body']
Cool stuff: playing with an API which requires authentication
Let's say you want to update your Twitter stream. Their status update method is a simple request, but it needs authentication (ie http://twitter.com/statuses/update.xml asks for your Twitter login and password)
Authentication in HTTP requests is achieved by sending a base64 encoded string of the username, a colon and the password (ie "login:password")
Our Twitter example would be something simple like:
- // You would edit the following:
- $username = 'joe'; // Twitter login
- $password = '123456'; // Twitter password
- $message = "Hey neat, I'm posting with the API";
- // Now, the HTTP request:
- $api_url = 'http://twitter.com/statuses/update.xml';
- $body = array( 'status' => $message );
- $headers = array( 'Authorization' => 'Basic '.base64_encode("$username:$password") );
- $request = new WP_Http;
- $result = $request->request( $api_url , array( 'method' => 'POST', 'body' => $body, 'headers' => $headers ) );
Can't be more simple, right?
Learn more
Jacob Santos being the documentation advocate he is, his class is fully commented, so just read the source to learn more. For instance, there are shortcuts to do GET, POST or HEAD request, you can pass more parameters such as a timeout limit, you can play with cookies and much more.
Please ditch the deprecated stuff
I almost feel stupid for writing an how-to guide for something that easy to use, but the thing is I have the feeling this class is heavily underused. For instance, as of writing I'm reviewing the plugins that were submitted in the Plugin Competition 2009, and this class is not exactly popular. Well, it should.
Don't reinvent the wheel using cURL, it's not always installed. Don't use class Snoopy, it's completely deprecated. Just use WP_Http!
Shorter URL
Want to share or tweet this post? Please use this short URL: http://ozh.in/of
Instead of creating a new instance every time, it is recommended you use the wp_remote_*() functions:
wp_remote_request();
wp_remote_get();
wp_remote_post();
etc.
scribu » Totally true especially if you need to instantiate the class a lot. I wanted to show the basic usage of the class, though :)
i agree with "Ozh" ..
"scribu" it can make the work faster, right? thanks for the details! :)
thanks for the info !!
Woar! Awesome Ozh! Thanks again for bringing this one to my attention!
enchskinnyasap » It won't make things faster (except faster to write I mean)
[…] PlanetOzh hacen un interesante tutorial de como lanzar peticiones HTTP mediante la API de WordPress. Desde la versión 2.7, disponemos de un interfaz muy sencillo para lanzar peticiones HTTP a […]
[…] PlanetOzh hacen un interesante tutorial de como lanzar peticiones HTTP mediante la API de WordPress. Desde la versión 2.7, disponemos de un interfaz muy sencillo para lanzar peticiones HTTP a […]
As a relative n00b to writing plugins, I really appreciate finding this article.
I had to go back and re-write about 50 lines of code, but it's totally worth it!
Thanks for the info.
How To Make HTTP Requests with WordPress…
Making HTTP requests in PHP is not difficult, and a variety of methods exists: using fopen(), using cURL extension, using file streams with fsockopen() and fwrite() for instance. The problem is: depending on server setup, this might or might not work o…
I had forgotten that the transports are only checked once, therefore it doesn't matter how many instances of the class exist, because they'll only do the check once.
The helper functions will probably be the most use to novices hoping to use the API. The class requires a bit more knowledge and error checking that the functions take care of. If you are using the class, then that is all up to you and it is expected that you know what you are doing.
I think I've been remiss to have not written documentation on the codex. Well, I have written some documentation on the codex, but it is sorely lacking details and from the last time I checked was filled with sarcasm.
I haven't yet needed to use get and post requests till date but will keep this in mind.
I'm confused as to whether this is a better option of the wp_remote* functions?
Ajay » It's really the same thing, they are wrapper functions for the class.
Makes sense…
btw, one thing about this blog, it doesn't save my details, so I need to keep filling in Name, Mail etc everytime I come back.
WP_Http doesn't seem to work all the time. I've seen certain blogs showing
RSS Error: WP HTTP Error: 1: Operation not permitted
on the Dashboard. It really is cool though.
[…] you are going to use it in WordPress, then you can use the inbuilt WP_Http class instead of curl as suggested by Ozh. The following code shows you how it can be done in WordPress 1 2 3 4 5 6 7 8 9 10 11 function […]
[…] Shared How To Make HTTP Requests with WordPress « planetOzh […]
[…] The last 5 post on planetOzh: Top 10 Most Common Coding Mistakes in WordPress PluginsBeing a Judge in the WordPress Plugin CompetitionSingle File WordPress Installer 2009 Open Source CMS Award: Nominate WordPress!How To Make HTTP Requests with WordPress […]
btw, one thing about this blog, it doesn't save my details, so I need to keep filling in Name, Mail etc everytime I come back.
Thanks for the handy tutorial :) I spent the past hour or so trying to figure out the best way to do this as I assumed the http API could only handle static files, but it appears I was wrong!
Hi
I used your twitter example to test and I always get the following error Fatal error: Class 'WP_Http' not found in /var/accounts/CN20060899/www/twitterapi.php on line 12
Any idea?
ximer » yeah, since I wrote this tutorial things changed slightly in WP. Now you need to explicitly include the class if you need it. I'll update the article.
I still get the same error. I think I'm making some kind of other mistake(s), kinda new at this kind of things.
I'm looking at the 3.0 changes (http://core.trac.wordpress.org/ticket/11559) on how they split out the class to class-http.php, and then considering your suggestion to essentially replicate what they did in http.php to include the class-http.php, and this feels a _little_ janky.
This are my thoughts:
while the WP_Http class SHOULD be present in all 2.7.x -> 2.9.x, say for some reason it wasn't, and we were in pre 3.x code, then the include would cause an exception because class-http.php isn't around until 3.x.
so with that in mind, why not use the wrapper functions found in http.php instead of including a .php and instantiating a new WP_Http yourself. Look at it this way: unless you're looking for advanced functionality, where you would need the WP_Http object itself, why not just use the wrappers since you know they've been there since 2.7 and you know they'll be there in 3.0 without any extra includes?
Thoughts? I'm working on 3.x compatibility right now for my plugin, and I don't want to commit and deploy something when I'm totally off the deep end ;)
lol, I just realize there are 3 pages of comments and saw your stuff from before talking about the wrapper functions. However my conundrum still stands I think, thoughts?
rev » yeah, totally, always used wrapper functions when they exist. I was just toying with the class to understand how it works
Nice article. I just started to write my first WP Plugin. Where can i find the complete list of "Wrapper Functions" for WordPress?
Actually, it's not the WP_Http class you have to use now, but the wrapper functions – wp_remote_get, etc: http://codex.wordpress.org/HTTP_API
Credit goes to @Viper007Bond ;)
Cheers!
i'm using this in a project i'm working on but there is one thing i just can't get to work. How do i use this to remote_get a GZip encoded api-response? i've tried with wp_remote_retrieve_body( wp_remote_get($url, array('decompress' => true)) ); and many other similair ways but i just can't get it to work. anybody got an idea how to do it?
Arvid » not sure I see where the problem is. When I wp_remote_get() a page that's gzipped, I get plain text just as a browser do. What's the particular API URL you're having problem with?
Good for screen scraping ala Digg's new link thing?
I'm quite new in this issue.
Anyone know how to speed things up?
I need to retrive a lot of Data (each Gallery Item) and things take Ages (1-5 sec.).
When I use this cache second load is fast, but the first still takes a lot of time.
And I don't wanna use Ajax in order to keep it search engine readable.
Anyone knows what how to speed things up?
sorry for sounding stupid, how do i test the result response? in POST
hi Ozh, do you have an idea when we get proxy support in the wrapper functions ?
Hello,
This is a wonderful article.
Is this do-able to use for automatically uploading a plugin to a wordpress site from the WP Repo? I would like to use it for a Web Application solution for WordPress.
Thanks!
I'm playing around with a server API which needs authorization with OAUTH. How can I use WP_Http to make this request??
Thanks in advance! :-)
Thanks sir, you save my day
Hello. Do anyone know what is all about this cookie acceptation thing? Is it safe?
Thanks for answer
is it possible to fetch contents of HTML forms on submission ??
Is it possible to set Content-Type and body to xml or atom+xml?
I set headers but no expected results: