Haven Rock XML and
open source software
for down-to-earth
business solutions
Google

havenrock.com whole Web

               
               
               
               
Developer Resources



NIRA Demonstration

  1. NIRA? What's that?
  2. What's REST?
  3. About the application
  4. How to install and use NIRA
  5. References

NIRA? What's that?

It stands for Naive Implementation of the REST Architecture.

What's REST?

It stands for REpresentational State Transfer. The term was coined by Roy Fielding in his dissertation[1]. The REST Architectural Style is basically an effort to rationalize and refine the way the Web already works. It describes the Web as being made up of Resources (pages or applications addressed with URIs), Components (e.g. web servers), and Connectors (such as HTTP), with URI-addressable Resources being the most important and distinctive characteristic.

Recently, Paul Prescod and others have suggested that REST may provide an alternative to RPC-based technologies for implementing Web Services.[2] Where the RPC model (exemplified by SOAP, the so-called Simple Object Access Protocol) entails a unique interface for every service, REST uses standard HTTP methods, meaning that a small and well-understood set of verbs (GET, POST, PUT and DELETE) is applied to a potentially infinite set of resources.

About the application

NIRA is a toy application that attempts to demonstrate one possible way of implementing REST-based web services (to the limited extent that I understand the idea). It uses Python and XSLT to return XML or HTML in response to HTTP GET requests.

The architecture of the application closely mirrors the URI hierarchy: for each node (or, if you like, step in the URI path), there is a corresponding directory in the host filesystem that contains a Python module and one or more XSLT stylesheets. Note that the REST architecture does not mandate this or any other way of structuring an application -- it simply helps, I thought, make the code comprehensible.

Cool features of NIRA:

  • Small -- about 320kb of code in all

  • Dynamically extensible -- you can add a new service node to a running server instance, and it will be automatically detected.

  • Plug-and-play -- if you have Python* and a supported XSLT processor**, you should be able to just unpack the archive and run a server. If you have an unsupported XSLT processor and know a little bit of Python, you should be able to add support for it very easily, provided it will write its output to STDOUT. Yeah, it's a kludge. The idea is to make the application as easy as possible to try out. See bin/runserver.py for more info.

    * Should work with Python 1.5.2 or later on POSIX platforms, or Python 2.x on Windows.

    ** Currently Saxon, 4xslt, and xsltproc.

Not so cool:

  • The way NIRA talks to the XSLT processor (os.popen()) is patently bogus (but see above). If this ever turns into a real application I will, of course, code to the appropriate APIs.

  • Having a Python module for each service node is kind of dumb, both because it requires a user to write the code (though that should be extremely easy if you know Python), and because it requires special import magic that wouldn't be necessary otherwise. On the other hand, this design may be good for a demo app, since it makes it easy to see what processes are taking place in each node.

  • The convention I adopted for obtaining the service description -- appending a ? to the end of the URL -- is probably a bad idea, since it overloads the query-string operator. Oh well. I'll try to come up with something better on the next iteration.

For more detail, see the API docs in doc/api, the examples in doc/examples, and the diagrams in doc/ .

How to install and use NIRA

Installation:

Download the NIRA package: http://www.havenrock.com/pub/REST/nira-20020212.tar.gz (Gzipped Tar archive, 57kb)

http://www.havenrock.com/pub/REST/nira0212.zip

Unpack the archive, and you should be ready to go!

Running a server instance:

   $ cd path/to/nira
   $ bin/runserver.py -d <data_dir> -p <port> -x <xslt_processor>
        

There are two prebuilt data directories called 'backend' and 'midtier'. So if you do something like this:

   $ bin/runserver.py -d backend -p 8480 -x xsltproc
   $ bin/runserver.py -d midtier -p 8580 -x 4xslt
        

you'll have an instant multi-tiered web application. To see what it does, visit URLs like

     http://localhost:8480/salesreport.
        

To get a service description, just add a question mark:

     http://localhost:8480/salesreport?
        

If you visit these with your browser, you will receive the HTML version. If you want to see the XML output, you can use lib/niraagent.py as a client (note that the command-line portion of this module has a hard-coded URL, which you may wish to edit).

There are other URLs you can access. Their paths are identical to the directory paths below backend/ and midtier/.

By the way, you might wish to know how the server determines which content type to return. Answer: it's done by magic ;-) Specifically, the server uses the HTTP Accept header. There's a problem with that, though: if you test for to use a generic 'text/html' or 'text/xml', well, most browsers accept multiple content types, and some accept 'text/xml'. You might choosing the content type that appears first among all the Accept: headers, but that seems unreliable. My solution was to use an application- specific content type called 'application/nira-xml', which is of course unknown to any browser. This is probably not the right way to do it, since it means you have to have a particular client in order to retrieve XML -- but otherwise, you have to use the URL, and I wasn't sure how to appropriately request a content type in the URL.

Creating your own service:

Each service node needs to have certain files in a subdirectory of the server data directory, e.g.:

     midtier/                          <- existing
         salesreport/                     ...
             _data/                       ...
                                               ------------------
             summary_by_office/        <- new          |  NODE  |
                 _data/                                ---------|
                     description.xml                            |
                     summary_by_office_filter.xslt [optional]   |
                     summary_by_office_html.xslt                |
                 main.py                                        |
                                               ------------------
        

The names _data, description.xml, and main.py are defined by the NIRA application; you can call the XSLT files whatever you like, but you must specify their names in main.py.

You can create a new service under a running server, and the server will automatically find the new node.

Another cool trick:

If you examine the contents of backend/salesreport/_data, you notice there are two data files, reps.xml and regional.xml, which contain identical data, except that regional.xml is broken down by region. The existing backend/salesreport/main.py specifies 'reps.xml' as the data source. Try changing 'reps.xml' to 'regional.xml', and watch what happens to the output (anser: not much -- the existing style- sheets continue to work).

  • "Architectural Styles and the Design of Network-based Software Architectures," Roy Thomas Fielding
  • "Second Generation Web Services," by Paul Prescod
  • Copyright © 2003 by Matt Gushee   ::  Last modified:  December 4, 2002