REST offers a powerful approach to building Web applications which allow you to quickly and easily define all of the routes used to interact with a particular application resource. So how does one go about actually implementing a RESTful approach?
As it happens, many Web development technologies support REST, among them Rails, the Zend Framework, and Spring. But when it comes to building an API, I prefer to use a lightweight yet capable solution which allows me to write the most compact syntax possible. For this purpose I’ve yet to find a more fitting solution than Sinatra. True to its Ruby roots, Sinatra’s compact syntax doesn’t come at a cost of readability, allowing you to create succinct yet immediately understandable APIs.
What Is REST Exactly?
The typical Web application is responsible for interacting with persistent data in four distinct fashions, known as CRUD operations, or Create, Read, Update, and Delete. For instance, we might create a travel application which compiles a list of the world’s greatest art museums. Users will logically wish to view a list of museums, view details about a specific museum, add new museums, update museum data, and occasionally remove a museum from the database. Understanding the important role CRUD operations play in Web applications, REST takes advantage of a logical URL structure and HTTP’s native request types (among the most common are GET, POST, PUT, and DELETE) to determine the intended outcome of the request. Continuing with the museum application example, the following URL request would be interpreted by an application which “speaks” REST to mean the client would like to retrieve a list of museums:
Likewise, retrieving a specific museum would also involve a GET request, but this time the request would be accompanied by a unique identifier associated with the desired museum:
Things start to get interesting when you consider the request used to create a new museum:
That’s right; the request is sent to the same endpoint as that used to retrieve the list of museums in the earlier example, however this time the request is sent via POST rather than GET, making the request unique in that regards.
So what sort of request would be used to update a museum? Believe it or not, we’d refer to the same endpoint used to retrieve a specific museum (
/museums/:id), but would use a request type of PUT:
To really blow your mind, deleting a museum also uses the same endpoint, but uses the request type of DELETE:
Sinatra is built atop the Ruby language, meaning you’ll need to first install a Ruby interpreter if you haven’t previously done so. Interpreters are available for all major platforms, and in fact is likely already installed on your machine if you’re running Linux or OS X. If you’re running one of these operating systems and don’t already have Ruby installed, or are running Windows, see this page for all of the installation details.
$ gem install sinatra
Once installed, you can make sure everything is working correctly by creating a simple application. Create a file named
app.rb and add the following contents to it:
get '/museums' do
'3 museums in database'
In this example we’re defining a GET route associated with the
/museums endpoint. When this endpoint is requested via GET, the string
three museums in database will be returned. Save this file and run it by executing the following command:
ruby -rubygems app.rb
== Sinatra/1.2.6 has taken the stage on 4567 for development with backup from Mongrel
As you can see from the output, Sinatra applications run by default on port 4567. Therefore to view the application fire up your browser and navigate to
http://localhost:4567/museums. You should see
three museums in database output to the browser.
$ gem install sinatra-jsonp
Once installed, revise
app.rb to look like this:
museums = [
"The Butler Institute",
get '/museums' do
Restart your Sinatra application and reload the webpage. You’ll see the following output:
["The Louvre","The Butler Institute","Doria Pamphilj"]
Incidentally, repeatedly restarting your Sinatra application quickly becomes tedious. Check out the shotgun gem, which will automatically restart your app every time it detects changes to the script.
Authenticating Users via an API Key
Most APIs require users to supply a valid API key with each request, which is subsequently checked against a database in order to ensure the requesting client is allowed to communicate with the API. While Sinatra doesn’t offer any native authentication capabilities, it’s pretty easy to incorporate such a feature into your application. Such a solution is explained in this Stack Overflow post.
Are you doing anything interesting with Sinatra? So far I’m having a blast, and would love to hear about how you’re getting along with it in the comments!
About the Author
Jason Gilmore — Contributing Editor, PHP — is the founder of EasyPHPWebsites.com, and author of the popular book, “Easy PHP Websites with the Zend Framework”. Jason is a cofounder and speaker chair of CodeMash, a nonprofit organization tasked with hosting an annual namesake developer’s conference, and was a member of the 2008 MySQL Conference speaker selection board.