In: , ,
On: 2009 / 08 / 16
Shorter URL for this post: http://ozh.in/of

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:

  1. if( !class_exists( 'WP_Http' ) )
  2.     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:

  1. $request = new WP_Http;
  2. $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:

  1. $url = 'http://search.twitter.com/search.json?q=rabbits';
  2. $request = new WP_Http;
  3. $result = $request->request( $url );
  4. $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:

  1. $body = array(
  2.    'nick' => 'ozh',
  3.    'mood' => 'happy'
  4. );
  5. $url = 'http://your.api.url/';
  6. $request = new WP_Http;
  7. $result = $request->request( $url, array( 'method' => 'POST', 'body' => $body) );
  8. // 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:

  1. // You would edit the following:
  2. $username = 'joe'; // Twitter login
  3. $password = '123456'; // Twitter password
  4. $message = "Hey neat, I'm posting with the API";
  5.  
  6. // Now, the HTTP request:
  7. $api_url = 'http://twitter.com/statuses/update.xml';
  8. $body = array( 'status' => $message );
  9. $headers = array( 'Authorization' => 'Basic '.base64_encode("$username:$password") );
  10. $request = new WP_Http;
  11. $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

Metastuff

This entry "How To Make HTTP Requests with WordPress" was posted on 16/08/2009 at 8:30 pm and is tagged with , ,
Watch this discussion : Comments RSS 2.0.

39 Blablas

  1. scribu says:

    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.

  2. Ozh says:

    scribu » Totally true especially if you need to instantiate the class a lot. I wanted to show the basic usage of the class, though :)

  3. i agree with "Ozh" ..
    "scribu" it can make the work faster, right? thanks for the details! :)

    thanks for the info !!

  4. marcO says:

    Woar! Awesome Ozh! Thanks again for bringing this one to my attention!

  5. Ozh says:

    enchskinnyasap » It won't make things faster (except faster to write I mean)

  6. […] 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 […]

  7. […] 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 […]

  8. Jeff says:

    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.

  9. php-html.net says:

    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…

  10. Jacob Santos says:

    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.

  11. Ajay says:

    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?

  12. Ozh says:

    Ajay » It's really the same thing, they are wrapper functions for the class.

  13. Ajay says:

    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.

  14. Mike Lopez says:

    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.

  15. […] 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 […]

  16. […] Shared How To Make HTTP Requests with WordPress « planetOzh […]

  17. […] 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 […]

  18. pimapen says:

    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.

  19. Ryan says:

    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!

  20. ximer says:

    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?

  21. Ozh says:

    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.

  22. ximer says:

    I still get the same error. I think I'm making some kind of other mistake(s), kinda new at this kind of things.

  23. rev says:

    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 ;)

  24. rev says:

    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?

  25. Ozh says:

    rev » yeah, totally, always used wrapper functions when they exist. I was just toying with the class to understand how it works

  26. EL says:

    Nice article. I just started to write my first WP Plugin. Where can i find the complete list of "Wrapper Functions" for WordPress?

  27. 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!

  28. Arvid says:

    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?

  29. Ozh says:

    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?

  30. nuwanda says:

    Good for screen scraping ala Digg's new link thing?

  31. 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.).

    1. function get_REST_xml($uri) {
    2.  global $settings;
    3.  $WP_http_class_cache = $settings['g3Url'];
    4.  
    5.  if (!isset($_SESSION['gallery3_cache'][$WP_http_class_cache]) ) {
    6.     echo "INFO: created new Session";
    7.     if( !class_exists( 'WP_Http' ) ){
    8.       require_once( ABSPATH . WPINC. '/class-http.php' );
    9.     }
    10.     $_SESSION['gallery3_cache'][$WP_http_class_cache] = new WP_Http;
    11.   }
    12.   if (! isset($_SESSION['gallery3_cache'][$uri])){
    13.     $this_req = $_SESSION['gallery3_cache'][$WP_http_class_cache]->request( $uri );
    14.     $_SESSION['gallery3_cache'][$uri] = json_decode($this_req['body']);
    15.   }
    16.   return $_SESSION['gallery3_cache'][$uri];
    17. }

    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?

  32. littlebearz says:

    sorry for sounding stupid, how do i test the result response? in POST

  33. juust says:

    hi Ozh, do you have an idea when we get proxy support in the wrapper functions ?

  34. Ryan Dennler says:

    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!

  35. Federico says:

    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! :-)

  36. Ded says:

    Thanks sir, you save my day

  37. Vavabrieria says:

    Hello. Do anyone know what is all about this cookie acceptation thing? Is it safe?

    Thanks for answer

  38. Aamir says:

    is it possible to fetch contents of HTML forms on submission ??

  39. Marko says:

    Is it possible to set Content-Type and body to xml or atom+xml?

    I set headers but no expected results:

    1. 'headers' => array('post-content' => 'application/xml'),
    2. 'body' => 'some xml here...'

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Gravatars: Curious about the little images next to each commenter's name ? Go to Gravatar and sign for a free account
Spam: Various spam plugins may be activated. I'll put pins in a Voodoo doll if you spam me.

Read more ?