August 18, 2011
Using Recess To Build a RESTful API
By DineEngine

Now with authentication! Accept no substitues.

In the beginning there was PHP, and it was not too shabby. You could easily make an RPC style API with little more than a single script. You might end up with requests like “/api.php?task=getUsers” or “/api.php?task=getUserFromId&id=4”. Your main api script might look like:

$task = $_GET['task'];

header('Content-Type: application/json");

switch ($task) {
  case 'getUsers':
    echo json_encode(get_users());
    break;
  case 'getUserFromId':
    $user = get_user($_GET['id']); // if you're lucky this wont throw an exception
    echo json_encode($user);
    break;
  // and so on
}

And, for smaller projects this would be sufficient. Perhaps you just want to expose the data in a single file, or in a small database. Whatever, it works, right?

What happens when you decide to scale up? More users. More data. More procedures. More complicated relationships. Your once simple (even elegant) RPC script is now 1500 lines long and you can’t remember what’s 800 lines up anymore. To add a new procedure you have to add a new case to your now overloaded switch. Perhaps you’ve been shuffling them off to functions, another function then. The key element here is the now the necessary practice of adding complexity through depth instead of complexity through breadth. Since you’re using remote procedures, you can’t simply just make another api file, api2.php? I don’t think so. Down this path lies ruin. How to escape?

A solution I’ve found is to use the lightweight, fairly simple, straightforward, web framework called Recess. Recess makes it very simple to create a RESTful webservice by allowing the developer to easily, and clearly, define routes for paths to data. Routing here is key since it allows us to easily expose data that is distributed and consistent across the entire API. A key concept in REST is to expose nouns, i.e. data, not verbs as in RPC. Routes are defined on a per controller, per action basis (Recess uses the MVC design pattern to great effect). This allows us to grow our API in a breadth first manner. If I want to add comments to my users, for example, all I do is define a comment model/view/controller trifecta, relate the model to my users model, and build out the comments controller to facilitate CRUD actions (and defining access control as necessary). In this way we aren’t adding comment capability to the users model (depth), we are building functionality alongside the users model (breadth) that compliments and integrates with it at the model level (using relationships, Recess’ ORM handles these very well).

To give a more concrete example of routes, here is some sample comment controller code (this code would actually work perfectly well as-is):

/** !Route GET */
function index() {
  $this->commentSet = $this->comment->all();
}

/** !Route GET, $id */
function details($id) {
  $this->comment->id = $id;
  if ($this->comment->exists()) {
    return $this->ok('details');
  } else {
    return $this->forwardNotFound($this->urlTo('index'));
}

The code above defines two routes for the comments model (with a route prefix of “comment/”), one for “comment” and one for “comment/$id”. The first is an empty route whose associated method “index” will always get called for requests to “mysite.com/comment”. The second is a dynamic route that passes the given id in the URL to the associated model. For example, a URL like “mysite.com/comment/5” would return me the details for a comment whose id property is equal to 5. This is all that is required for Recess to generate content for our model’s data. If the client included a JSON accept header, Recess would return a JSON representation of the model’s data. If not, Recess might render an HTML listing of the model’s data (whose views we configure ourself). We could also omit the accept header and just call “mysite.com/comment/5.json” to get a JSON response.

Recess also handles some of the more gritty, lower level things for us like parsing out request parameters into named method parameters that get passed to your function, a built-in developer console, skeleton code generation, etc. It also has a very capable ORM. You can drop down to SQL if you really need to, as well (notably the ORM doesn’t handle OR conditions…). It will also handle content types intelligently for us, as discussed above. These are but a few features recess exposes to us developers (one of my other favorite features is the ability to add very modular plugins), which are a welcome addition to any toolbox.

In short, Recess, in combination with a RESTful API design allows us to remove depth complexity from our API projects. It does this by providing an excellent MVC structure, which we leverage to expose data through routes, down to controllers, through the model, and output through the view. I would recommend Recess for any developer looking to build a small-medium sized API with minimal resources, little ramp up time (everyone knows PHP/MySQL right?) and great down the road scalability.

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

Trusted by top brands.

Get Started with DineEngine.

Contact Us Now Find Out How Chepri Can Help Your Team. Ask Us More About Using Recess To Build a RESTful API.

(800) 338-8102

733-C Lakeview Plaza Blvd. Worthington, OH 43085.