How To: Making a PHP REST client to call REST resources

A lot of companies these days (including Amazon and Yahoo!) are exposing their web services in the form of REST resources. At a high level REST is pretty easy to understand, all you’re doing is exposing a web service in the form of a URL. Users can then query this URL, through HTTP methods like GET and POST. REST calls generally return some type of XML or Object Encoding like JSON.

An example would be Yahoo!’s Geocoding API, with the following URL:

Code:
http://api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&street=701+First+Street&city=Sunnyvale&state=CA

I would get:

Code:
<Result precision="address">
   <Latitude>37.416384</Latitude>
   <Longitude>-122.024853</Longitude>
   <Address>701 FIRST AVE</Address>
   <City>SUNNYVALE</City>
   <State>CA</State>
   <Zip>94089-1019</Zip>
   <Country>US</Country>
</Result>

So Yahoo! exposes the Geocode URL and allows you to query this resource using URL parameters like appid and street. Dynamically building your URL to query a given resource is OK, generally that’s what people do, like the following:

Code:
$base = 'http://xml.amazon.com/onca/xml3';
$query_string = "";

$params = array( 'ManufacturerSearch' => "O'Reilly",
    'mode'  => 'books',
    'sort'  => '+salesrank',
    'page'  => 1,
    'type'  => 'lite',
    'f'     => 'xml',
    't'     => 'trachtenberg-20' ,
    'dev-t' => 'XXXXXXXXXXXXXX' ,
);

foreach ($params as $key => $value) {
    $query_string .= "$key=" . urlencode($value) . "&";
}

$url = "$base?$query_string";
$output = file_get_contents($url);

The problem here, is that REST is meant to take advantage of HTTP methods GET, POST, PUT, DELETE, etc.. When people are showing examples which dynamically build queries and call file_get_contents, the average user doesn’t appreciate (understand) what type of request is being made. Do they care? Should they care? We’ll that’s another story. Eventually though, more intense REST resources will become widely available, and it will be critical the user (developer) understands if their making a POST or PUT request.

I came across a great PEAR package the other day called HTTP_REQUEST, which among many things supports GET/POST/HEAD/TRACE/PUT/DELETE, basic authentication, proxy, proxy authentication, SSL, file uploads and more. Using this package, I got started on a simple wrapper class called RESTclient, which gives intuitive support for making REST resource calls.

So if I was going to use RESTclient to call the Geocode API above, it would look like this:

Code:
<?php

require_once "RESTclient.php";

$rest = new RESTclient();

$inputs = array();
$inputs["appid"] = "YahooDemo";
$inputs["street"] = "701 First Street";
$inputs["city"] = "Sunnyvale";
$inputs["state"] = "CA";

$url = "http://api.local.yahoo.com/MapsService/V1/geocode/"
$rest->createRequest("$url","POST",$inputs);
$rest->sendRequest();
$output = $rest->getResponse();
echo $output;

?>

At this point, you might be thinking, who cares — what’s the difference between using a loop to dynamically generate the URL or RESTclient. There are lots of reasons, first off, I can easily call the Geocode resource again using another address just by changing:

Code:
$inputs["street"] = "1600 Amphitheatre Parkway";
$inputs["city"] = "Mountain View";

There was no need to re-generate the URL. Furthermore, I’m explicitly specifying a POST request. Just as easily I can make a PUT, DELETE, etc. request on a given resource by changing the createRequest method parameters.

The class below is RESTclient. Note, I put this together to prove a point, it still needs some work if you plan on using it.

Code:
<?php

require_once "HTTP/Request.php";

class RESTClient {

    private $root_url = "";
    private $curr_url = "";
    private $user_name = "";
    private $password = "";
    private $response = "";
    private $responseBody = "";
    private $req = null;

    public function __construct($root_url = "", $user_name = "", $password = "") {
        $this->root_url = $this->curr_url = $root_url;
        $this->user_name = $user_name;
        $this->password = $password;
        if ($root_url != "") {
            $this->createRequest("GET");
            $this->sendRequest();
        }
        return true;
    }

    public function createRequest($url, $method, $arr = null) {
        $this->curr_url = $url;
        $this->req =& new HTTP_Request($url);
        if ($this->user_name != "" && $this->password != "") {
           $this->req->setBasicAuth($this->user_name, $this->password);
        }        

        switch($method) {
            case "GET":
                $this->req->setMethod(HTTP_REQUEST_METHOD_GET);
                break;
            case "POST":
                $this->req->setMethod(HTTP_REQUEST_METHOD_POST);
                $this->addPostData($arr);
                break;
            case "PUT":
                $this->req->setMethod(HTTP_REQUEST_METHOD_PUT);
                // to-do
                break;
            case "DELETE":
                $this->req->setMethod(HTTP_REQUEST_METHOD_DELETE);
                // to-do
                break;
        }
    }

    private function addPostData($arr) {
        if ($arr != null) {
            foreach ($arr as $key => $value) {
                $this->req->addPostData($key, $value);
            }
        }
    }

    public function sendRequest() {
        $this->response = $this->req->sendRequest();

        if (PEAR::isError($this->response)) {
            echo $this->response->getMessage();
            die();
        } else {
            $this->responseBody = $this->req->getResponseBody();
        }
    }

    public function getResponse() {
        return $this->responseBody;
    }

}
?>

Related Articles:

Follow me on Twitter!

Your Ad Here

25 Responses to “How To: Making a PHP REST client to call REST resources”

  1. Raja Nagendra Kumar, says:

    Does any one know of similar client for J2ME pl.

  2. Ghassem says:

    Thanks; there is a little bug in your test code at this line :
    $url = “http://api.local.yahoo.com/MapsService/V1/geocode/”
    you forgot the tailing “;”.
    $url = “http://api.local.yahoo.com/MapsService/V1/geocode/” ;

    I have a question: how can I find the target site has or has not this service, and how you find out REST of Amazon and Yahoo?
    Please response me soon,I’m waiting!

    Thanks

  3. George A. Papayiannis says:

    Hi Ghassem,

    Sorry for the delay in responding, I get so much spam on this blog now that it’s hard to stay on top of these things. The only way to know if the site supports REST is to take a look at their developer areas. For example at Yahoo for PHP it would be this page and at Amazon this page.

    Good luck,
    George

  4. manuj says:

    Hi george i was going thru ur blog….
    Just want to make a suggestion regarding ur spam concern in ur blog… use

  5. manuj says:

    Akismet
    http://www.akismet.com

  6. George A. Papayiannis says:

    Hi Manuj,

    Thanks for the tip, I have Akismet turned on and it catches a lot of the spam, but still stuff gets through.

    Talk to you soon,
    George

  7. Logu says:

    thanks, very useful.
    I need to upload a file to REST Server, How can i do that using RESTClient class

  8. arnod'mental says:

    Nice article, I’m englued into a SOAP client/server and as services start to get more and more complex I think I’ll migrate to REST (before it’s too late…).

    > Logu :
    You could create a POST or PUT request, sending 2 or 3 variables for your file : file name, mime type (optionally), and a base64_encode of the file itself (retreived using file_get_contents for example)
    Then on the serverside you will need to create a new file with the specified name and write into it the base64_decode of the sent variable.

  9. rim says:

    wew, great article.

    I need to know more about REST, could you please help me. How do I know the response is from yahoo api ??

    I’ve try it, but I got no result than err…

    thanks

  10. rim says:

    could you please give me HTTP/Request.php library…

    I don’t have it… Or where should I can find it..

    thanks

  11. ravi says:

    hi!
    can you tell me more about REST…
    i dont have enough knowledge about it..

  12. rohit kumar says:

    hi

    i don’t have enough knowledge about rest.

    please can u tell me how to connect through a MySQL server which can ONLY be accessed from the REST server.

    regards
    rohit

  13. php5rrr says:

    you can also use stream_context_create() to set the method for the request.
    example:
    $postdata=http_build_query(Array(’can’=>’pippo’,'pesce’=>’palla’));
    $opts= Array ( ‘http’=>Array(
    ‘method’=>’POST’,
    ‘header’ => ‘Content-type: application/x-www-form-urlencoded’,
    ‘content’=>$postdata
    ));
    $resource=stream_context_create($opts);
    file_get_contents(”http://localhost/example/post.php”, false, $resource);

  14. Adam B says:

    I like to use cURL in php for connecting to REST services. Simply call the URI and then use simpleXML to parse the response. simple, takes less than 15 lines to get a very simple client to work.

  15. Adam B says:

    The function i use to access REST services

  16. Adam B says:

    // PHP Functions needed to access various APIs
    function get_REST_xml($uri, $rawXML = 0)
    {
    global $parsed;
    global $uri;
    $getXML = curl_init() or die(curl_error()); // initialize curl handle
    curl_setopt($getXML, CURLOPT_URL,$uri); // set url to post to
    curl_setopt($getXML, CURLOPT_FAILONERROR, 1);
    curl_setopt($getXML, CURLOPT_FOLLOWLOCATION, 1);// allow redirects
    curl_setopt($getXML, CURLOPT_RETURNTRANSFER,1); // return into a variable
    // curl_setopt($getXML, CURLOPT_SSL_VERIFYHOST, 2);
    // curl_setopt($getXML, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($getXML , CURLOPT_HEADER, 0);
    curl_setopt($getXML, CURLOPT_TIMEOUT, 3); // times out after 4s
    // curl_setopt($getXML,CURLOPT_POST,1); // Set the method as post
    // curl_setopt($getXML, CURLOPT_POSTFIELDS, "key=".$API_key);
    $pulledXML = curl_exec($getXML);
    //echo ("");
    //print_r(curl_getinfo($getXML));
    //echo ("");
    // echo "\n\ncURL error number:" .curl_errno($getXML);
    // echo "\n\ncURL error:" . curl_error($getXML);
    // ...close cURL handle ($getXML) below

    curl_close($getXML);
    if ($rawXML == 0)
    {
    $parsed = simplexml_load_string($pulledXML);
    return $parsed;
    }
    elseif($rawXML == 1)
    {
    return $pulledXML;
    }
    else
    {
    echo "Function Error";
    }
    }

  17. simo says:

    hallo,
    can somebody help me to consum a webservice using php curl and xerces with data from MySQL…I am a newby but i make it subjectif “learning by doing”
    thanks a lot

  18. simo says:

    Sorry I wanna mean how many script shall I write for this action! Request Response and parsing with xerces.
    Thanx

  19. Peter says:

    There is a great Eclipse plugin where you can visually construct your REST call: http://http4e.roussev.org/

    Of course this is not an PHP client, yet it is very priceless tool for REST and HTTP.

  20. Adolfo says:

    how rest work with this kind of uris … http://api.local.yahoo.com/MapsService/V1/geocode?appis without extension… it sounds more familiar
    http://api.local.yahoo.com/MapsService/V1/geocode.php?appis

    thanks

  21. Jaspreet says:

    Hi,
    can anyone help me in using REST.
    Lets say i have link (http://dev.ss-build.com/server2/services/application.wadl).
    It have a method
    How can i access or use or call this method .
    Now, let us say i have created a php page containing form where i will enter my email and password.
    now when i click on login after entering my mail and password.
    It should use this method and we can say a session will start and i will able to acess the other page.
    Now can any one tell me how can i do this??
    What should i write in ACTION
    please give a example.

  22. Jaspreet says:

    this is the method > loginForm
    what should i write in form action means in .. .action=”???” m

  23. Geddy says:

    George, excellent article. However, I’m trying to begin writing my own lightweight REST class for use with Amazon Web Services, but I’m confused by one thing in your class:

    require_once “RESTclient.php”;

    Is this line just assuming that we have *some REST client* to use? Which one would you recommend using? I only need to send GET requests for the time being. If you could reply to this, it’d be much appreciated :)

    Thanks man,
    -Geddy

  24. tester says:

    I want to know what is the content of file HTTP/Request.php.
    What is in this file?

  25. otto06217 says:

    http://pear.php.net/package/HTTP_Request/

    The author mentioned this pear package above.

    I hope this helps.

    Within the next days I’ll try it out.

    Regards

    otto06217

Leave a Reply

Line and paragraph breaks automatic.
XHTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>