PHP Serving RESTful APIs Supporting Multiple Formats - Supercoders | Web Development and Design | Tutorial for Java, PHP, HTML, Javascript PHP Serving RESTful APIs Supporting Multiple Formats - Supercoders | Web Development and Design | Tutorial for Java, PHP, HTML, Javascript

Breaking

Post Top Ad

Post Top Ad

Friday, June 21, 2019

PHP Serving RESTful APIs Supporting Multiple Formats

PHP Serving RESTful APIs 


Supporting Multiple Formats


Problem

You want to support multiple formats, such as JSON and XML.

Solution

Use file extensions:

       http://api.example.com/people/rasmus.json
       http://api.example.com/people/rasmus.xml

       // Break apart URL
       $request = explode('/', $_SERVER['PATH_INFO']);

       // Extract the root resource and type
       $resource = array_shift($request);
       $file = array_pop($request);
       $dot = strrpos($file, ".");
       if ($dot === false) { // note: three equal signs
            $request[] = $file;
            $type = 'json'; // default value
       } else {
            $request[] = substr($file, 0, $dot);
            $type = substr($file, $dot + 1);
       }

Or support the Accept HTTP header, to allow requests to http://api.example.com/people/rasmus:

       GET /people/rasmus HTTP/1.1
       Host: api.example.com
       Accept: application/json,text/html

       require_once 'HTTP2.php';
       $http = new HTTP2;
       $supportedTypes = array(
             'application/json',
             'text/xml',
       );
   
       $type = $http->negotiateMimeType($supportedTypes, false);
       if ($type === false) {

             http_response_code(406); // Not Acceptable
             $error_body = 'Choose one of: ' . join(',', $supportedTypes);
             print json_encode($error_body);
       } else {
             // format response based on $type
       }

If all else fails, read a query parameter:

       http://api.example.com/people/rasmus?format=json
       http://api.example.com/people/rasmus?format=xml

       $type = $_GET['format'];

Discussion

When your RESTful API supports multiple formats, such as JSON and XML, there are a few ways to allow developers to signal which format they want to use.

One option is to use file extensions, such as http://api.example.com/people/rasmus.json and http://api.example.com/people/rasmus.xml. Because these aren’t real files, this requires some parsing of $_SERVER['PATH_INFO']:

       // Break apart URL
       $request = explode('/', $_SERVER['PATH_INFO']);

       // Extract the root resource and type
       $resource = array_shift($request);
       $file = array_pop($request);
       $dot = strrpos($file, '.');
       if ($dot === false) { // note: three equal signs
            $request[] = $file;
            $type = 'json'; // default value
       } else {
            $request[] = substr($file, 0, $dot);
            $type = substr($file, $dot + 1);
       }

       // $type is json, xml, etc.

You pull off the file segment of the URL and search for the trailing ".“. If it’s not there, fall back to a default value. If it is, then extract the resource name and type using substr().

The downside to using file extensions is that clients can only request one specific representation type. If they ask for a JSON version and you don’t support that, then there’s no way for them to signal an acceptable alternative format in the same request.

Multiple representations for a resource can live at a single location, such as http://api.example.com/people/rasmus. In this case, clients can specify a list of formats in their preferred order. Then you can negotiate with the client to return the resource in the best mutually agreeable format.

In this case, the client passes a request like so, using the Accept HTTP header to signal its preferences:

       GET /people/rasmus HTTP/1.1
       Host: api.example.com
       Accept: application/json,text/html

Unfortunately, proper parsing of the Accept header isn’t easy. So, use a library, such as PEAR’s HTTP2:

       require_once 'HTTP2.php';
       $http = new HTTP2;
       $supportedTypes = array(
              'application/json',
              'text/xml',
       );

       $type = $http->negotiateMimeType($supportedTypes, false);
       if ($type === false) {
             http_response_code(406); // Not Acceptable
             $error_body = 'Choose one of: ' . join(',', $supportedTypes);
             print json_encode($error_body);
       } else {
             // format response based on $type
       }

This lets you specify that you support JSON and XML and uses the $http->negotiateMimeType() function to return the client’s most preferred format from the list you support.

As a last result, you can accept the format as a query parameter:

       $type = $_GET['format'];

Though simple and easy to implement, this is not considered a proper RESTful design.



No comments:

Post a Comment

Post Top Ad