http://www.developer.com/lang/rubyrails/building-an-ajax-friendly-rest-api-with-sinatra.html

Back to article

Building an Ajax-friendly REST API with Sinatra


September 19, 2011

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:

GET /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:

GET /museums/:id

Things start to get interesting when you consider the request used to create a new museum:

POST /museums

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:

PUT /museums/:id

To really blow your mind, deleting a museum also uses the same endpoint, but uses the request type of DELETE:

DELETE /museums/:id

Installing Sinatra

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.

The Sinatra repository is hosted on GitHub, however it's most easily installed via RubyGems:

$ 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:

require 'sinatra'

get '/museums' do
  '3 museums in database'
end

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.

Returning JSONP

One typical reason for creating an API is to provide authorized third-parties with access to the API interface in order to at a minimum retrieve the data made available via the API, and potentially even manipulate the data using other defined routes. These days it's become very common to perform these API requests using Ajax, sending the request to the desired API endpoint and receiving JSON-formatted data in return. However, it's not possible for JavaScript to connect to another server other than the one upon which the JavaScript script resides, due to a security policy known as same origin. One great workaround to this dilemma is a variant of JSON known as JSONP, or JSON with padding. Although Sinatra doesn't by default support JSONP, it's easy to add JSONP capabilities using the sinatra-jsonp gem:

$ gem install sinatra-jsonp

Once installed, revise app.rb to look like this:

require 'sinatra'
require "sinatra/jsonp"

museums = [
  "The Louvre",
  "The Butler Institute",
	"Doria Pamphilj"
]

get '/museums' do
  JSONP museums
end

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.

Conclusion

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.

Sitemap | Contact Us