The Best Reason for REST

REST is a popular means of implementing Service Oriented Architectures (SOA) as well as merely providing simple remote APIs for interacting with systems. REST is a constraint based architecture built on HTTP, the foundational protocol of the Web. That foundation, its simplicity and the constraints it is built upon are its biggest strengths.

1. Simple Foundation

URLs and HTTP are the basis of building REST services.

1. a. HTTP

HTTP is a fairly simple, well understood protocol. Almost any developer who has built a web based application has come to understand the basics of HTTP. It is a stateless protocol with a limited number of request methods it uses. It is made up of 8 total verbs. From a practical point of view, those verbs are broken into Control Methods and Action Methods. The Control Methods are really only there to inspect the HTTP protocol. The Action Methods are the ones that are really used to perform the real work of interacting with a Web server.

Control Methods:

  1. HEAD
  2. TRACE
  3. OPTIONS
  4. CONNECT

Action Methods:

  1. GET
  2. POST
  3. PUT
  4. DELETE

1. b. URLs

URLs refer to resources. Those resources are manipulated using HTTP to pass data from client to server.

2. Existing Knowledge Base

Beyond your average Web Developer there are a large number of people that know HTTP and its semantics. They know how to build scalable solutions. They have knowledge about implementing caching, load-balancing, proxying, etc. In addition there is built up knowledge around network routing, security, DNS, etc. Leveraging existing knowledge in a solution is often a very good idea.

3. Constraint Based

All resources have to be represented as a URL. Those Action Methods that I referred to above constitute the total number of actions that you can take upon a resource in a RESTful architecture. So you can represent a resource and act upon it with four distinct verbs.

The Best Reason

The best arguments for REST are SOAP, OASIS and WS-*. The more I read those specs, the more I think that REST is a better solution. There seems to be a very strong correlation between people who want to build “Enterprise” solutions and people who want those solutions to be complex. It’s as if complexity is somehow a valuable attribute. It’s as if the only way to solve a complex problem is with a complex solution.

I believe that complex problems do not always require complex solutions. In fact, managing and hiding complexity is one of the best ways to deal with complex problems. Software developers do it all the time when they program. Whether that’s through a shared routine or through Object Oriented techniques like Polymorphism, software developers are constantly striving for simpler solutions to complex problems. In this way we combine small, simple solutions together to solve larger, more complex problems.

REST is that simple solution. It’s based on a simple, well known protocol. There are simple, well known techniques that can be used to solve complex security and scalability issues. The constraints of REST itself largely eliminates the need for complex descriptions of Services like WSDL. XML Schemas of the messages themselves and a list of URLs is generally enough.

Need to authenticate once and then pass a token on subsequent requests? Use a cookie.
Need to route messages based on schema version? Use HTTP redirects.
Need to change the location of an endpoint? Change your DNS entry.
Need to secure messages in transit? Use SSL.
Need to secure your endpoints? Use a firewall and/or use Client SSL Certificates.
Need to audit usage? Use the same tools you do for a web site.
Need to scale? Implement load balancing, or use caching techniques.

Conclusion

Sometimes we need to do remoting. Sometimes we would like to build a loosely coupled, distributed architecture. There are quite a few techniques we can use to do that. Sometimes we need to be technology neutral in those implementations. The field is narrowed a bit. I think when I look at REST sometimes I look at it through the lens of alternatives. One of the most common alternatives is SOAP and the WS-* stack. And when I look at REST through that lens, things look quite rosy on the REST side.

All Database Backed Web Apps are “Just CRUD Apps”

It’s time to end the debate between “Just simple CRUD Apps” and “more complex” apps.

Very complex behavior can be expressed through a small set of fairly simple rules. This is often described as emergent behavior or just emergence. The general idea is that simple building blocks can construct complex systems – atoms form molecules, molecules form proteins form cells, forms a human. Each of the building blocks is simple, but the end result is an amazingly complex organism.

The same use of sets of simple commands often is expressed in software development. In object-oriented development, groups of simple methods are used to create more complex behavior. Likewise simple objects collaborate to form more complex behavior. Likewise all of the databases in the world answering questions about all kinds of things, aggregating and filtering, are being manipulated by four simple statements. To access data using SQL, you use four simple commands:

SQL

  • SELECT
  • INSERT
  • UPDATE
  • DELETE

What other SQL operations are there? None. The only other things you can do are DDL operations to modify a database schema. Every operation that can be done to manipulate data in a schema can be expressed by some combination of these four simple statements.

REST/HTTP

  • GET
  • POST
  • PUT
  • DELETE

HTTP happens to map the same concepts as SQL to simple Verbs. While HTTP supports a few other Verbs – OPTIONS, HEAD, TRACE, and CONNECT – these methods are generally for diagnostics, discovery and proxy support. Two independent protocols have defined the same set of general purpose actions and have decided that they are the only ones needed. I would hazard a guess that this is not a coincidence.

The input from the user and the storage of the system can only be manipulated using four simple commands that correspond to Create, Read, Update and Delete. These simple, constrained sets of operations allows you to build systems that solve complex problems. As a software developer you’re doing something wrong if the way that you are building an application doesn’t allow you to start simple and only add complexity as needed. Software is at its best when it is only as complex as it needs to be to solve the problem at hand. Software is also at its best when it can easily be modified to add complexity as needed without drastic rework. Intentionally imposing some constraints on a design can help enforce a consistent, simple design through the entire system.

Interact with REST Services from the Command Line

REST is becoming more popular as a means of implementing Service Oriented Architectures (SOA) as well as merely providing simple remote APIs for interacting with systems. The main reason for this is that it provides a very simple means of creating and consuming Services. Contrasted to SOA implementations like SOAP and REST can be a relief of simplicity.

One of the main advantages of REST is that it requires no tooling to use. Unlike SOAP, it is very easy to construct ad-hoc clients to consume a RESTful service. These examples use curl a command-line utility available on Unix systems or using Cygwin on Windows. The same concepts can be translated to anything that can send HTTP requests.

Example REST Service with Ruby on Rails

As the example implementation, I’ll use a Ruby on Rails controller. Rails has very good support for implementing RESTful services so is easy to show.

To get started with this example you can generate a Rails project and the Order object with the following commands:

rails order_example
cd order_example
./script generate resource order name:string

Then you can implement a RESTful controller with the following code:

class OrdersController < ApplicationController # GET /orders # GET /orders.xml def index @orders = Order.find(:all) respond_to do |format| format.html # index.rhtml format.xml { render :xml => @orders.to_xml }
end
end

# GET /orders/1
# GET /orders/1.xml
def show
@order = Order.find(params[:id])
respond_to do |format|
format.html # index.rhtml
format.xml { render :xml => @order.to_xml }
end
end

# POST /orders
# POST /orders.xml
def create
@order = Order.new(params[:order])
respond_to do |format|
if @order.save
flash[:notice] = 'Order was successfully created.'
format.html { redirect_to order_url(@order) }
format.xml { head :created, :location => order_url(@order) }
else
format.html { render :action => "new" }
format.xml { render :xml => @order.errors.to_xml }
end
end
end

# PUT /orders/1
# PUT /orders/1.xml
def update
@order = Order.find(params[:id])
respond_to do |format|
if @order.update_attributes(params[:order])
flash[:notice] = 'Order was successfully updated.'
format.html { redirect_to order_url(@order) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @order.errors.to_xml }
end
end
end

# DELETE /orders/1
# DELETE /orders/1.xml
def destroy
@order = Order.find(params[:id])
@order.destroy
respond_to do |format|
format.html { redirect_to orders_url }
format.xml { head :ok }
end
end
end

This controller allows you respond to all of the Actions that can be taken on a Resource: GET, POST, PUT and DELETE.

Command Line Interaction with the Service

Start our Rails application and then you can see the following commands at work.

./script/server

Get a list of all of the Orders

The first thing you want to do is get a list of all of the orders in the system. To do this we perform a GET command asking for an XML response. The URI in this case represents a list of all the Orders in the system.

curl -X GET -H 'Accept: application/xml' http://localhost:3000/orders

Get a single Order

If we want to get the XML representation of a single order then we can ask for a specific Order by changing the ID to a URI that represents just one Order.

curl -X GET -H 'Accept: application/xml' http://localhost:3000/orders/15

Delete an Order

REST keeps things simple by having consistent Resource URIs. The URI that represents Order number 15 can also be used to Delete or Modify that Order. In this case the URI for the GET is the same, but we ask it to delete the Order instead.

curl -X DELETE -H 'Accept: application/xml' http://localhost:3000/orders/15

Modify an existing Order

Just as with delete, if we want to modify an Order we use the URI that represents that specific Order. The only difference is that we have to tell the server that we are sending it XML, and then actually send the XML.

curl -i -X PUT -H 'Content-Type: application/xml' -H 'Accept: application/xml' \
-d 'Foo' http://localhost:3000/orders/15

Create a new Order

Creating an Order looks very similar to modifying an Order but the URI changes to the Resource URI for the collection of all Orders. The response to this command will be an HTTP 302 Redirect that gives you the URI of the newly created Order Resource.

curl -i -X POST -H 'Content-Type: application/xml' -H 'Accept: application/xml' \
-d 'Foo' http://localhost:3000/orders/

Conclusion

I think you can see how easily you can interact with a REST service using only the most basic tools available, namely simple Unix command line utilities. This simplicity offers a lot of power, flexibility and interoperability that you lose when you implement services with more complicated implementations such as SOAP. That’s not to say that SOAP and all of the WS-* specifications don’t have have their place, because they do. When you can implement a simple solution and meet your needs you will often find that solution to have a surprising amount of added benefits such as flexibility.