Making Remote Requests with wp_remote_get

When it comes to working with remote requests on the server side, there are usually two solutions that I end up seeing.

In fact, there are two solutions that I’ve typically ended up using:

Both of these functions generally work well; however, in our experience with Standard, we’ve had less than stellar experience especially when it comes to budget hosts.

This is where wp_remote_get comes into play. In short, wp_remote_get is a simple WordPress API function that’s used to retrieve data from a specified URL using the HTTP GET method.

Understanding wp_remote_get

Of course, as with most API methods, there’s a little more to it than that.

But first, I want to note that my general thought process, as it relates to WordPress, is as follows:

  • If a function exists in the WordPress API for a given task, use it
  • Otherwise, look for a similar function in PHP
  • And if that doesn’t work, write my own

Rarely – if ever – have I had to write my own. WordPress usually has something available and, if not, PHP has you covered 9 times out of 10.

The challenge, though, is knowing how to find functions like this in the WordPress Codex. Honestly, it’s not always easy.

In fact, I went for a long time without using wp_remote_get, but I think I finally stumbled across when one afternoon while going through Rarst’s Query Posts website.

Here’s How It Works

So anyway, if you’re in the business of writing plugins, themes, or application-related code that needs to make a remote request, here’s how you can go about doing it using wp_remote_get.

Assuming that your URL is ‘http://foo.com’, then you’d simply do something like this:

// Define the URL
$url = 'http://foo.com';

// Make the request
$response = wp_remote_get( $url );

Easy enough, right? But here’s the thing: The request can fail, and in those cases you should be prepared to handle that.

First, you can check to see if the request failed by using the is_wp_error function. If it did fail, then you can proceed by trying to use file_get_contents. If that fails, then you can use cURL, and if that fails, you may simply be out of luck.

All joking aside, here’s how an implementation of the logic may look:

/**
 * Defines the function used to initial the cURL library.
 *
 * @param  string  $url        To URL to which the request is being made
 * @return string  $response   The response, if available; otherwise, null
 */
private function curl( $url ) {

	$curl = curl_init( $url );

	curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
	curl_setopt( $curl, CURLOPT_HEADER, 0 );
	curl_setopt( $curl, CURLOPT_USERAGENT, '' );
	curl_setopt( $curl, CURLOPT_TIMEOUT, 10 );

	$response = curl_exec( $curl );
	if( 0 !== curl_errno( $curl ) || 200 !== curl_getinfo( $curl, CURLINFO_HTTP_CODE ) ) {
		$response = null;
	} // end if
	curl_close( $curl );

	return $response;

} // end curl

/**
 * Retrieves the response from the specified URL using one of PHP's outbound request facilities.
 *
 * @params	$url	The URL of the feed to retrieve.
 * @returns		The response from the URL; null if empty.
 */
private function request_data( $url ) {

	$response = null;

	// First, we try to use wp_remote_get
	$response = wp_remote_get( $url );
	if( is_wp_error( $response ) ) {

		// If that doesn't work, then we'll try file_get_contents
		$response = file_get_contents( $url );
		if( false == $response ) {

			// And if that doesn't work, then we'll try curl
			$response = $this->curl( $url );
			if( null == $response ) {
				$response = 0;
			} // end if/else

		} // end if

	} // end if

	// If the response is an array, it's coming from wp_remote_get,
	// so we just want to capture to the body index for json_decode.
	if( is_array( $response ) ) {
		$response = $response['body'];
	} // end if/else

	return $response;

} // end request_data

/**
 * Retrieves the response from the specified URL using one of PHP's outbound request facilities.
 *
 * @params	$url	The URL of the feed to retrieve.
 * @returns			The response from the URL; null if empty.
 */
private function get_response( $url ) {

	$response = null;

	// First, we try to use wp_remote_get
	$response = wp_remote_get( $url );
	if( is_wp_error( $response ) ) {

		// If that doesn't work, then we'll try file_get_contents
		$response = file_get_contents( $url );
		if( false == $response ) {

			// And if that doesn't work, then we'll try curl
			$response = $this->curl( $url );
			if( null == $response ) {
				$response = 0;
			} // end if/else

		} // end if

	} // end if

	// If the response is an array, it's coming from wp_remote_get,
	// so we just want to capture to the body index for json_decode.
	if( is_array( $response ) ) {
		$response = $response['body'];
	} // end if/else

	return $response;

} // end get_response

Notice above that we define a function to initialize cURL and set the proper parameters. Next, we define a get_response function is that responsible for working through the various ways that we can make a request and grab the response.

The last thing to notice is that if the request is successful using wp_remote_get, then an array will actually be returned. Though you may care to examine, say, the headers, the example above has us examining the body; otherwise, the other functions will return the data of the body.

As mentioned in the comments and according to the WordPress source code, the WP_HTTP object will actually do the following:

* The order for blocking requests is cURL, Streams, and finally Fsockopen.
* The order for non-blocking requests is cURL, Streams and Fsockopen().

In my experience with building Standard, we’ve actually not had a 100% success with wp_remote_get, but we’ve had to fall back to cURL and, sometimes, file_get_contents.

But here’s what’s interesting: the HTTP API clearly uses cURL. Unfortunately, I’ve not done enough investigation as to know why wp_remote_get may fail, but the cURL function above has proven successful.

I suspect that it may have to do with the exact cURL parameters or some other set of configuration but, again, that’s pure speculation (as I hate admitting that :)).

But Let’s Make It Easier

As important as I think that it is to understand the various strategies that come with dealing with remote requests, I think that it’s just as useful to have libraries available to help make our jobs easier.

Luckily, thanks to pointers from Ryan McCueGeorge MamadashviliAndrey Savchenko, and Bronson Quick, it is easier thanks to the WP HTTP API. This particular article gives a break down of all of the HTTP API methods that are available in WordPress for making HTTP requests, so be sure to review this when you’re looking to manage more advanced request options.

5 Comments

The WP HTTP API uses cURL – it’s the first transport it tries. So having cURL as a fallback in case of error is probably not going to do much good (unless you’ve found a bug in WP’s implementation). Also, I’m curious to know about the circumstances where the WP API transports (cURL, streams, fsockopen()) have all failed, but file_get_contents() has worked. Do you have specific examples of public APIs where that’s the case?

    I wish I had more to offer :/.

    You’re right in the the WP HTTP API uses cURL – the example that I’ve provided above is actually from some work that we’ve done in in the past on Standard. Truth be told, we’ve had some erradict results with using just the single API.

    We see this primarily on budget hosts (that is, hosts that charge an extraordinarily low amount for usage – think $4.95 a month). In order to make sure that we’re able to make outbound requests, we have to try the three different versions to in order to ensure the request is actually successfully made.

    We’re actually spending some time digging into the core API to see what the problem may actually be for our latest release. It’s been a bit of a thorn ever sense we implementation that feature.

Nice article, Tom. Very helpful.

Trackbacks and Pingbacks

WordPress news: May 5 to May 11, 2013March 18, 2014 at 8:55 am

[…] introduction to the wp_remote_get function with good examples on its […]

Leave a Reply

Name and email address are required. Your email address will not be published.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>