REST-Based Web Service Server Serving Proprietary XML Documents

June 20, 2007 · Filed Under Ruby on Rails 

RESTfor our purposesis really the same thing as a simple web GET request: it requires no special server setup or request encoding and decoding. You simply use your favorite web server and serve your results in whatever format you choose to designusually a custom XML format. Regardless of the implementation language, most developers agree that REST services are simple to build and flexible enough to adapt to your needs. Additionally, if you closely adhere to the true intent of REST, you can take advantage of any HTTP-based filters and security measures your server has in place. Because of these types of benefits, and REST’s simplicity, most of the web services out in the “real world” are REST services, rather than SOAP or XML-RPC services.

When it comes to Rails applications, RXML templates help make it simple to build REST-based servers with custom XML documents. In fact, to build REST-based web servers with Ruby on Rails, you really only need to:

  1. Make sure you turn off layouts for the methods you’ll be using in your service

  2. Associate RXML templates with the methods in your controllers, instead of RHTML templates

Let’s build a simple service to demonstrate. Here’s a controller with some dummy data. Update your existing code_controller.rb file from the previous examples to contain this new restserver method and layout command:

class CodeController < ApplicationController
 layout "application", :except => [:restserver]
 def restserver
   @sampledata = ["Kevin","Timothy","Catherine"]
 end
end

Here’s the view associated with the controller; save it as restserver.rxml in the app/views/code directory):

xml.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
xml.exampledata do
  counter = 0
  @sampledata.each do |rec|
     counter = counter + 1
     xml.name(rec, :id => counter)
  end
end

And just like that, your simple REST-based server is done! REST clients can access the service at the URL http://localhost:3000/code/restserver.

Custom XML generated by our REST-based web service

 

This example used one additional Ruby library: the Builder library. According to its documentation, the Builder library “provides a simple way to create XML markup and data structures.” It gets installed with Rails by default, but if you want to make sure you have the latest version, you can use the gem command:

gem install builder

Complete documentation on the Builder library can be found at http://builder.rubyforge.org.

The controller for our application is very simplein fact, too simple. In real life, the controller would include other actions associated with a “regular” web site. So let’s assume those methods exist and that they use standard RHTML templates. We need to disable the layout, but only for those actions that are part of the REST service (the restserver action). So we call the layout method with the except parameter:

layout "application", :except => [:restserver]

We’ve disabled the layout, but what about any action-specific templates? RHTML templates take precedence over RXML templates. If you have both restserver.rhtml and restserver.rxml in your views/code directory, restserver.rhtml will be used for rendering. So it’s important to be careful about your file extensions when building REST-based services.

That’s about all there is to the controller; the restserver method just packs an instance variable with data that the view will put into the XML document.

The view (in this case, an RXML template) uses the Builder library to build an XML document. Rails’ ActionPack library knows to use the Builder library to render this view because of the RXML extension. Using Builder to generate your XML is straightforward. Since we want our document to be a true XML document, we start by calling the xml.instruct method, where xml is an XML document object that’s available in any RXML template:

xml.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"

To add tags to the document, we call methods on the xml object. The method name is the name of the tag. The tag’s content (the text between the beginning and ending tags) is the first parameter to this method. Pass any attributes for this tag as hash values. Here’s a very simple example:

xml.name("Kevin", :id => 1, "age" => "31")
# creates <name id="1" age="31">Kevin</name>

In a real document, of course, you need to deal with nested tags. You can nest tags by defining the children tags inside the block of the parent tag:

 xml.exampledata do
     xml.name("Kevin")
 end
 # creates <exampledata><name>Kevin</name></exampledata>

Additional details and complete documentation on the Builder library can be found online at http://builder.rubyforge.org/.

As you can see, building REST web services really is straightforward. But you still need to do a lot of grunt work: you need to create an XML document, then tell your clients how to parse your proprietary documents and how to invoke your service. This is one of the main reasons SOAP and XML-RPC were created: to give web services a standard for communication between the server and client. SOAP and XML-RPC allow developers to build clients without spending a lot of time learning how to communicate with the server for each new service. So let’s shift focus to building SOAP and XML-RPC servers.


Comments

Leave a Reply

You must be logged in to post a comment.