How to implement the REST technology

written by: Emanuela Hedrick; article published: year 2006, month 08;


In: Root » Internet » APIs and Web Feeds » How to implement the REST technology

Dutch French Spanish Portuguese Italian German Japanese Chinese Korean Russian Arabic Bookmark and Share this Article

There are two sides to this tale, the first is how to generate legitimate REST requests, and the second is how to handle the responses correctly.

Generating Requests

When it comes to generating the request, you have three main options. First, you can generate the request manually, using PHP's header functions. This gives you complete flexibility in generating the request, but does involve the most coding. Second, you can use one of PHP's built-in request functions such as file_get_contents() or file()/fopen(), fread(), and fclose(). With this method, a lot of the detailed information is handled automatically by PHP, and you receive the same response. Finally,you can use a custom class designed to be used with the API in question. Generally these classes require nothing more than the parameter list, and will return the results in the form of a custom object or make them accessible through a class.

Manual Generation

Generating requests manually is only tricky the first time, after that, code-reuse and modularity kick in. Conceptually the function that will generate the request is pretty basic. First, all the request parameters are prepared to ensure proper transmission. Next, the URL for the endpoint is generated, then parsed and broken up into its component parts. Finally, the request itself is sent using sockets:

functioncallAPI($endpoint, $devkey, $action, $type, $keyword)
{
  $action = urlencode($action);
  $type = urlencode($type);
  $keyword = urlencode($keyword);

Three of the passed parameters are URL encoded. This is necessary to ensure they are passed properly over the URL. In the previous example, a search for "style" was performed; if the search had instead been "style book," the space would have required encoding, resulting in style%20book. I have neglected encoding the devkey variables, trusting that the issuing authority took how it would be used into consideration when creating them.

  $url = $endpoint ."?devkey=$devkey&action=$action&type=$type&keyword=$keyword";
  $url_info = parse_url($url);
  $host = $url_info['host'];
  $path = $url_info['path'] . "?" .$url_info[‘query'];
  $data = "";

Here the URL itself is generated, including the now URL-encoded parameters. The URL needs to be deconstructed down to its component parts for use in the raw socket connection.

  $fp=fsockopen($host, 80);
  fputs($fp, "POST ". $path ."HTTP/1.1\r\n");
  fputs($fp, "Host: ". $host."\r\n");
  fputs($fp, "Accept: */*\r\n");
  fputs($fp, "Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n");
  fputs($fp, "Connection:close\r\n");
  fputs($fp, "Content-Type:application/x-www-form-urlencoded\r\n");
  fputs($fp, "Content-Length: ".strlen($data) . "\r\n\r\n");
  fputs($fp, "$data");

Here the information generated by previous code is finally sent. The first fputs() line sends the path to the requested document, and the second line specifies the desired host.

  $response="";
  while(!feof($fp))
  {
    $response.=fgets($fp, 128);
  }
  fclose($fp);
  list($http_headers,$http_content)=explode("\r\n\r\n", $response);
  return $http_content;
}

Finally, the response is retrieved and the content of the response is returned. You learn how to handle responses in the sections dealing with that side of things shortly.

Quick Generation

Utilizing PHP's built-in file functions, the same process can be completed with much less code (though you do have less flexibility). Conceptually this function works the same as the previous one, except all the file socket calls are replaced with one call to file_get_contents():

functioncallAPIQuick($endpoint, $devkey, $action, $type, $keyword)
{
  $action = urlencode($action);
  $type = urlencode($type);
  $keyword = urlencode($keyword);
  $url = $endpoint ."?devkey=$devkey&action=$action&type=$type&keyword=$keyword";
  $response = @file_get_contents($url);
  return $response;
}

There really isn't much to explain with this example. The URL encoding was discussed previously, and the single file_get_contents() call handles all the magic. The ampersand in front of the function call is used to suppress any warnings that may arise from a non-existent file or URL, because these should be handled by the calling function (file_get_contents() will return false in these instances). In pre-PHP5 environments you will need to use fopen() instead of file_get_contents(). Some flexibility is lost with this request type, because you can no longer set custom headers or optional headers, which may be required or very desirable depending on the API with which you are interacting.

Automated Tools

As the popularity of web services increases, so will the prevalence of prebuilt classes to handle the dirty work of actually interacting with the server. If the service you want to interact with has a class available, it is definitely worth looking into. Accessing the class will of course be dependent on the class itself. It should come with sufficient documentation, and access will likely not differ too much from the earlier examples — just with a little more error checking (you hope). Something to keep in mind is that many prebuilt modules are developed and maintained by third parties, and as such you might have to wait a while after new features are released on the API for them to become available with your class.

Handling the Response

How you deal with the response depends on which method of sending the request you choose. If you generated the request either manually or with the aid of one of PHP's built-in functions (like file_get_contents()) you will also need to manually handle the response. If you used a third-party module, it will have its own interface for retrieving results.

Manually Parsing the Response

The response provided by the server should be an XML document; luckily, XML was designed to be easy to parse. Unfortunately, no matter how it was designed, manually parsing anything usually isn't a lot of fun. PHP5 comes with SimpleXML, which makes handling XML documents a breeze. PHP4 users don't have SimpleXML; however, a few third-party modules like MiniXML are available that perform similar functions.

Once you have received the response, sticking it into a SimpleXML object should be a breeze. Using the previous library example and request function, you end up with something like this:

$response= callAPIQuick('http://library.example.com/api.php', '123', 'search',
'book',‘style');
if($response)
{
  $xml = simplexml_load_string($response);
  print_r($xml);
}else
{
  echo "Error loading feed";
}

Here, the response is not false (and hence something, presumably the XML you were hoping for, was returned). Note that this assumption is generally pretty valid. When a server providing an API encounters an error, it should provide the error in a nice XML format. The simplexml_load_string() function takes the response and turns it into an XML object that can be directly accessed, iterated through, and so on. Finally, the print_r() function results in a user-friendly output showing the contents of the object, shown here:

SimpleXMLElement Object
(
 [Request] => SimpleXMLElement Object
  (
   [RequestId] => 123a456
   [Parameters] => SimpleXMLElement Object
   (
     [Argument] => Array
     (
       [0] => SimpleXMLElement Object
       (
       )
       [1] => SimpleXMLElement Object
       (
       )
       [2] => SimpleXMLElement Object
       (
       )
       [3] => SimpleXMLElement Object
       (
       )
     )
   )
  )
 [Response] => SimpleXMLElement Object
  (
   [ResultCount] => 2
   [Item] => Array
   (
     [0] => SimpleXMLElement Object
     (
       [Title] => Style Book Vol 1
       [Status] => Out
       [Holds] => 3
       [CopiesOnHand] => 2
       [Author] => Jon Doe

     )

     [1] => SimpleXMLElement Object
     (
       [Title] => Style Book Vol 2
       [Status] => In
       [Holds] => 0
       [CopiesOnHand] => 1
       [Author] => Jon Doe
     )
   )
  )
)

Looking at that output, a couple things should be immediately obvious:

  • SimpleXML does a lot of really useful things for you very quickly.

  • The resultant objects don't display attributes (see the argument list under parameters). The data is in there, it just isn't shown with a print_r().

  • Arrays start counting at 0 (just like everywhere else in PHP, it's just something to keep in mind).

  • The Item array is just begging to be handled with a foreach() loop.

Bearing all that information in mind, a couple of quick lines of code are all that is required to explore the content more fully.

echo "You searched for: {$xml->Request->Parameters->Argument[3]->Value}<br>";
echo "Here are your {$xml->Response->ResultCount} results<br>";
foreach($xml->Response->Item AS &$item)
{
echo "{$item->Title} by {$item->Author}<br>";
}

Here the search query and result count is presented, and then the results themselves are iterated through. The syntax gets a little weird when dealing with arrays (as demonstrated when the search query is printed), so it is often sensible to iterate through them for clarity.

REST is an effective method of querying remote APIs when it is permissible for the request portion of your transaction to take place in the clear. Creating REST queries is as easy as URL-encoding the required parameters and specifying an endpoint for the call. Dealing with REST responses can be a little trickier; however, by leveraging tools like SimpleXML, it too can be completed quickly.

Disclaimer

1) E-articles is not responsible for the information contained by this article as well for any and all copyright infringements by authors and writers. E-articles is a free information resource. If you suspect this article for any copyright infringement, please read the terms of service and contact us to investigate the problem.
2) E-articles is not responsible for inaccuracies, falsehoods, or any other types of misinformation this article may contain and will not be liable for any loss or damage suffered by a user through the user's reliance on the information gained here.

link to this article