In this tutorial, we'll learn about the WordPress HTTP API, and the different functions it offers to make HTTP requests and handle the response.
Introduction
There are a variety of ways to make HTTP requests with PHP. For instance, the most popular are "fopen
" and "curl
"; and different web hosts have different levels of support for them. When you develop for WordPress, you have to ensure that your code works across as many hosts as possible. A solution that supports all the different transport methods is thus required.
Since version 2.7, WordPress implemented the "WP_Http
" class to address this issue by providing a standardized API to make HTTP requests. This class will automatically pick and use the transport API that is supported by the web host.
"The WordPress HTTP API provides a cross-compatibility solution. You should always use it if possible."
Some Basics About HTTP Requests
HTTP (acronym for HyperText Transfer Protocol) is the protocol used by web browsers to transfer information over the Internet. When you load a web page (like this one), you send a request to the server; and then you get back a response. There are different request methods (like GET, POST, HEAD, PUT) and also many response status codes (like the infamous 404 when a page is not found).
I'm not going to dive more into this profound topic, but this should give you a basic idea of what we are going to do: make an HTTP request to a URL and get back the response. Sure you can do this with your browser, but we'll learn how to do this inside WordPress. The advantages or possibilities are limitless. You can make requests to grab feeds, JSON files, XML data or full web pages.
As we mentioned above, WordPress has a class that simplifies making HTTP calls. The class name is "WP_Http
" and the concerned method is "$wp_http_instance->request($url)
". This method returns the result of the HTTP request which we'll detail later.
if( !class_exists( 'WP_Http' ) ) { include_once( ABSPATH . WPINC. '/class-http.php' ); } $request = new WP_Http; $args = array (); $result = $request->request( 'http://mysite.com' , $args );
Since this bit of code is a little long (and repetitive if you do many requests), WordPress provides a simpler function which does exactly the same thing:
$arg = array (); wp_remote_request ('http://mysite.com', $arg);
In the arguments array, you can specify one or more of the request parameters. One of these parameters is the request method. If you are making a "GET" request:
$arg = array ( 'method' => 'GET'); wp_remote_request ( 'http://mysite.com' , $arg );
It goes even further with 3 additional helper functions for the GET, POST and HEAD request methods since they are used most:
-
wp_remote_get()
– Retrieves a URL using the GET HTTP method -
wp_remote_post()
– Retrieves a URL using the POST HTTP method -
wp_remote_head()
– Retrieves a URL using the HEAD HTTP method
It's highly recommended that you use the helper functions instead of the WP_Http
class. That's what they are made for.
Doing Our First HTTP Request
So let's make our first HTTP request. I have chosen Bitcoinica as the service we'll be pulling the data from. There are a couple of reasons for that. First, most of the tutorials pick the Twitter API; and second the Bitcoinica API is RESTful, simple and well documented. You can find the full API documentation on their website.
If you don't know Bitcoinica, it's a trading service for Bitcoins (a virtual currency). Their API provides a bunch of functions: Getting the latest quote for a currency pair, placing orders, following positions, etc.
The first request will pull the latest quote for a given currency pair. The API documentation is quite important as it mentions the URLs to make the calls to and the expected response. To make things easier, I put the code into a plugin and also stop WordPress from loading the theme. This will make the results look cleaner without cluttering the HTML code of the theme.
<?php /* Plugin Name: Bitcoinica Ticker Plugin URI: http://mystore.com Description: Retrieves Bitcoinica prices Author: Abid Omar Version: 1.0 */ add_filter ('template_redirect', function() { $response = wp_remote_get ( 'https://www.bitcoinica.com/api/quotes/BTCUSD.json', array ( 'sslverify' => false ) ); var_dump($response); exit; });
Parsing the HTTP Response
When you load your blog, you should get something similar to this:
array( 'headers' => array( 'server' => string 'nginx/0.7.67' (length=12) 'date' => string 'Fri, 09 Mar 2012 16:38:30 GMT' (length=29) 'content-type' => string 'application/json; charset=utf-8' (length=31) 'connection' => string 'close' (length=5) 'status' => string '200 OK' (length=6) 'strict-transport-security' => string 'max-age=31536000' (length=16) 'x-ua-compatible' => string 'IE=Edge,chrome=1' (length=16) 'etag' => string '"578a43c47f9d9d5f4159bcd1a6f63f06"' (length=34) 'cache-control' => string 'max-age=0, private, must-revalidate' (length=35) 'x-request-id' => string '07bb51e7df9f0a4a50718fa7af21cc76' (length=32) 'x-runtime' => string '0.007439' (length=8) 'x-rack-cache' => string 'miss' (length=4) ) 'body' => string '{"buying":4.89989,"pair":"BTCUSD","selling":4.9639}' (length=51) 'response' => array( 'code' => int 200 'message' => string 'OK' (length=2) ) 'cookies' => array( empty ) 'filename' => null )
This is the full HTTP response. In reality, it's in plain text but WordPress simplifies it in this array. Below is the real HTTP response
HTTP/1.1 200 OK Server: nginx/0.7.67 Date: Fri, 09 Mar 2012 21:32:09 GMT Content-Type: application/json; charset=utf-8 Transfer-Encoding: chunked Connection: keep-alive Status: 200 OK Strict-Transport-Security: max-age=31536000 X-UA-Compatible: IE=Edge,chrome=1 ETag: "93b5e5de369c0a1d83a16aa5a787b60d" Cache-Control: max-age=0, private, must-revalidate X-Request-Id: e4332f7b46ef751703d817216b7816d1 X-Runtime: 0.008076 X-Rack-Cache: miss { "pair": "BTCUSD", "selling": 4.96854, "buying": 4.86172 }
The first line (in the plain-text HTTP response) is the HTTP protocol version as well as the response status code. What follow is the response headers, a set of key and value pairs, and then you have the response body. WordPress arranges this information into the response array.
Handling Errors
But what if something goes wrong and we can't connect to the server? This can happen for various reasons like the server being down, takes too much time to answer or the SSL certificate verification fails. In this case, WordPress returns a WP_error
object which explains the error.
object(WP_Error)[33]( public 'errors' => array( 'http_request_failed' => array( 0 => string 'Could not resolve host: www.bitcoinicau.com; Host not found' (length=59) ) ) public 'error_data' => array( empty ) )
An improved version of our script could be:
<?php /* Plugin Name: Bitcoinica Ticker Plugin URI: http://mystore.com Description: Retrieve Bitcoinica prices Author: Abid Omar Version: 1.0 */ add_filter ( 'template_redirect' , function () { $response = wp_remote_get ( 'https://www.bitcoinica.com/api/quotes/BTCUSD.json', array ( 'sslverify' => false ) ); if ( !is_wp_error ($response) ) { echo $response['body']; } exit; });
is_wp_error
checks whether the passed variable is a WP_Error
object. This is not enough, however, to know that the returned response is a valid and successful one. A 404 (Page not found) or 503 (Service not available) is a valid response. An additional check of the response status code is necessary. This will depend mainly on the service or website you are making requests to.
WordPress has even more helper functions that retrieve the data from the HTTP response.
-
wp_remote_retrieve_body()
– Retrieves just the body from the response. -
wp_remote_retrieve_header()
– Gives you a single HTTP header based on name from the response. -
wp_remote_retrieve_headers()
– Returns all of the HTTP headers in an array for processing. -
wp_remote_retrieve_response_code()
– Gives you the number for the HTTP response. This should be 200, but could be 4xx or even 3xx on failure. -
wp_remote_retrieve_response_message()
– Returns the response message based on the response code.
The Arguments Array
You can have a finer degree of control over your HTTP queries. The second argument takes an array of key/value pairs. Here is a summary of the most important ones:
-
method – when using the
wp_remote_request
method, you should specify which request method you are using (GET, POST, HEAD, PUT, etcÖ). The default value is GET - timeout – The time in seconds before WordPress drops the connection and returns an error. The default value is 5 seconds which is a relatively short time if you are connecting with a slow and busy server.
- redirection – Specifies the times to follow a redirect before giving up. The default amount is also 5.
- cookies – An array of cookie values passed to the server.
For a complete and more detailed list, check out HTTP_API » Other_Arguments in the WordPress codex website.
SSL Certificate Verification
If you looked carefully at the code above, you'll notice that I'm already using the second argument in the wp_remote_get
function and setting the 'sslverify
' property to false. I did this because my web server doesn't have any certificate's authorities installed and thus won't recognize any of them. If you want to verify the host you are connecting to before making the connection, you'll need a list of certificates' authorities installed in your web server.
Web browsers recognize a variety of certificates' authorities. When the certificate is verified the web browser is happy and shows a green lock icon at the top. (The icon differs from one browser to another but it's almost always green, and most of the time on the left of the address bar)
If the certificate is rejected, the connection fails and a WP_Error
object is returned.
Conclusion
This was an introduction to the WordPress HTTP API. In this tutorial, we learnt the very basics of making an HTTP request and reading the response. In the next tutorial, we'll learn how to use the HTTP API to build a PayPal payment gateway and process express checkout payments.
Comments