blog :: web development :: rest :: design rest architecture

Designing A RESTful Architecture

Posted on 07 Dec 2008 by - Permanent link Trackback this post Subscribe to this post Comment on this post -   

Graph Doodle

We’re finally up to part five in our series on REST APIs, so by now you should be familiar with URLs, HTTP, understanding and using RESTful APIs.

If you’ve made it this far on our journey, I think it’s safe to assume that your you’re a bit of a coder, which is good because in this installment we talk about how to provide a RESTful API to your own web services.

URLs Again

You might have your own ideas of the kind of services or data you want to expose via an API or maybe you’re reading this to understand the motivations behind some APIs that you already know. Either way, we’re going back to the start of the series to take another look at the URL, which, you remember, identifies a unique resource. This post uses an example of a shop with products in different categories so a product URL might look like this:

http://myshop.com/categories/toys/products/steam-train-0023/

Performing a HTTP GET on this URL would return a representation (in HTML, XML or JSON) of the data that we have on the “steam train” toy.

If we wanted information on the “toys” category itself, we would GET this URL:

http://myshop.com/categories/toys/

Now, take a look at this URL, which returns a set of all the products that are classed as “toys”

http://myshop.com/categories/toys/products/

Does this break the rule that a URL identifies a unique object? No, because the collection is itself an object, much like the “shopping basket” that Brian Hendrickson and I had a useful discussion over in the comments on REST examples earlier in this series. We can create, read, update and delete collections - they are just a little more abstract than products or baskets.

RESTful URL Patterns

Notice the pattern in all the RESTful URL examples that I’ve been using in this series? No? Then have a look at these:

base_url/name/id/name/id/
base_url/name/id/name/
base_url/name/id/

In the shopping example, the base_url is just the domain name, but it’s very common to see sub-directories of domains, like https://api.del.icio.us/v1/.

After that we see combinations of names (“categories”, “products”) and identifiers (“toys” “stream-train-0023”) If the RESTful URL ends in an identifier, it returns a single object. If it ends in a name it returns a collection of objects. That is a beautifully simple yet powerful pattern.

Not Names But Axes

OK, now I want you to forget about names and identifiers and instead think about axes and values. Yes, axes, like on a graph:

base_url/axis1/value1/axis2/value2/axis3/value3/

Any mathematicians reading are hopefully saying “Aha!” right now, but the rest of us might need a bit more help with this concept. Try this URL:

http://mygraph.com/x/1/y/2/z/1/

It represents the point (1,2,1) in 3D, whereas this...

http://mygraph.com/x/1/y/2/z/

...is a plane, or the collection of all points on the Z-axis constrained by x=1 and y=2.

I’m trying to get you to think at a higher level than web coders typically have to do. A well designed architecture should have a basic model which makes sense at the most abstract level, so think in terms of relational algebra, set theory and matrix arithmetic.

Graph Theory

Returning The Data

You’ll have respond to requests with either a HTTP error code (such as 404 Not Found) or a representation of the resource. The last named axis in the URL defines what type of resource you’ll be returning. Outputting a collection is there’s no subsequent value or the object on its own if there is.

You need to sit down and do some interface design now, paying particular attention to:

  • Calculate (and document) exactly what data should be returned for each type of resource you’ll be returning.
  • What formats will you support when describing resources? XML, JSON, HTML, PHP?
  • You should provide an error document with a HTTP error. What data will you include to describe the error?
  • Think about paging and rate limiting now, not when your servers collapse under heavy loads.
  • Your interface will change over time. Yes it will. How will you manage the transition from version 1 to version 2?
  • URL parameters, specifying things like output format, application keys, paging offests, search parameters etc. Include these in your specifications.

There’s a lot to think about in that list and you should realise that it’s not good to just build a SQL statement out of each URL component. Take the API design you created above and make a matrix, plotting each type of URL against the four HTTP request methods, like this:

GETPOSTPUTDELETE
http://myshop.com/categories/
http://myshop.com/baskets/
http://myshop.com/baskets/1/
http://myshop.com/categories/toys/products/steam-train-0023/
http://myshop.com/categories/toys/products/
http://myshop.com/categories/toys/

Now, for each of the blanks you need to specify a handler or decide that the handler is innappropriate (for example, if the API cannot delete a category). Each handler will be a function or class in your server application. If you are using a Model-View-Controller framework, the handlers will not be a Model, View or Controller - they will be a bridge.

Remember that your API must remain stable no matter how much your application architecture changes.

Practicalities

Any API will come in for some serious abuse, not just from malicious users but from prototype, untested applications so you’ll need to plan ahead. Consider implementing these features now:

  • Banning users by username, IP address or referrer
  • Rate limiting & timeouts
  • Caching
  • Paging
  • Returning HTTP code 304 Not Modified
  • Supporting the HTTP If-Modified-Since header

Testing your API is vital but at least it should be pretty easy. Using a tool like curl or wget to automate calls and then validate the output against XML schemas etc. Don’t forget to run some load tests too.

Conclusion

Phew, finally at the end of this series and it’s been fun to write and stirred up some great discussion.

Did I cover everything you wanted? If there’s still some uncertainty, then please ask in the comments.


Creative Commons licensed photos by briankennedy and Khalil Sawant.

0 Trackbacks

Trackbacks are closed for this story.

0 Comments

Comments are closed for this story.

 

Sitemap

Copyright © 2006-2009 MMMeeja Pty. Ltd. All rights reserved.