When you read about REST these days it is usually in the context of APIs. You’ll even find REST being discussed in Web Service and SOA circles. A REST API makes an application’s data and functionality available to other programs according to the principal of REST.
Sometimes you see the term REST API and sometime REST Service (or RESTful Web Service). I don’t like the REST Service term because I think it gets confused with the SOAP and RPC styles. REST API is also a strange term. When we think of APIs the most familiar is the local call to a function, method, subroutine or procedure. The remote procedure call tries the best it can to preserve the same semantics when the caller and callee are not on the same machine. When we think of a remote API it is easy to assume RPC. With REST the focus is on the resources. Other aspects of the interface such as the set of method are fixed and uniform. I use REST API to mean a RESTful application data layer that can be consumed by another program.
REST is an architectural style for hypermedia systems with the World Wide Web being the primary example, and the only instance of immediate concern. For all the talk of APIs the web is still mainly about UI. Its a hypermedia system for humans.
REST doesn’t care if it is a human or a program that is the client of your resources. So why all the focus on APIs? Other than general information about REST I have not found practical specific advice for implementing RESTful web applications. The best I have found is this slide deck â€” I wish I saw the talk.
An information only web site (one with static HTML and no forms) is likely to be RESTful even if only by accident. As web sites allow richer interaction between the user and the site and among users of the site it gets easier to stray from the principals of REST. Some of the issues that come up are:
- The HTML form element doesn’t support PUT and DELETE
- You need somewhere to put conversational (i.e. session) state and REST says no cookies
- You need to authenticate users but can’t accept the limitations of HTTP authentication
Is it these issues that caused REST to retreat to the realm of APIs?
Now ajax can help solve these problems so its reasonable to think about making your web app UI RESTful. XHR does support PUT and DELETE (as well as GET and POST). There are a few options for maintaining state on the client:
- Gears or HTML 5 client storage can store session state and more
- HTML 5 session history can handle specific issues with the back button
Authentication is still an issue and the solution to CSRF requires server side session state. I need to think more about these.
Lets assume all the issues with your web app UI being fully RESTful are solved. Now you want to also provide your application’s functionality/data to other arbitrary clients. Do you do this as a completely independent effort? It makes sense to me that the UI should be using the same RESTful data layer API that other clients would use.
Now you have two related but separate planes of URLs; UI URLs and data URLs. You will find yourself in the same situation by following the principals of SOFEA if you try to make the UI and data layer RESTful.
While looking at a list or table of accounts the UI URL might be something like myapp.com/ui#accounts (the hash is used because I’m assuming a single page app) and the URL for the resource supplying the account collection might be myapp.com/api/accounts. The names of accounts in the list include links to details about each account. Clearly, for bookmarking, the UI URL needs to include the account identifier. The UI URL for an account detail view might be myapp.com/ui#accountdetails;083249. The data URL could be myapp.com/api/accounts/083249.
If your RESTful data layer follows the principal of “hypermedia as the engine of application state” then the /api/accounts representation should have (in some form or another) the URLs to each account in the collection. The accounts list UI also needs to know the the UI URL for account details.
To click a link and get from the accounts list to an account detail vew there are two things that must be done. First the accounts list UI must know how to take the account id number and add it to the account details UI URL. There is nothing in the uniform REST interface that tells the UI how to do this. In fact programs should not pick apart URLs (there seems to be some debate about if it is OK for programs to assemble URLs) .
Second the account details UI needs to know the data URL to use for the specific account. Here are some ways it could happen:
- The details page could know how to create data URLs taking the account number from its own URL and sticking it in the right place. I think the article “Describing RESTful Applications” is saying this isn’t OK.
- The accounts list page could put the data URL somewhere in memory (or other client storage if it isn’t a single page app) so that the account details page can retrieve and use it. But this wouldn’t work for bookmarking.
- The UI URL could have the full data layer URL encoded in it like so: myapp.com/ui#accountdetails;/api/accounts/083249. This solves the bookmarking problem but something just doesn’t feel right about this URL. If nothing else its long and repetitive.
Articles on RESTful APIs (including the above linked “Describing RESTful Applications”), put a lot of emphasis on loose coupling between servers — the things providing the API — and clients. There seems to be an underlying assumption that generic or arbitrary clients exist.
In my past experience of building desktop applications the UI has detailed knowledge of the underlying data. In traditional MVC architecture (if there is such a thing) the views know about the model (the views can call methods of the model to get or set data) but the model has no direct access to the views. Some sort of publish subscribe event notification is used by the model to let the views know about changes. The main motivation is to allow multiple different views for the same data. What does this have to do with web apps? Most web apps don’t need change notifications in the form of server push. The point here is that the UI is tightly coupled to the model but the model has no direct dependency on the UI. The model is there to serve the needs of the UI but is not impacted by its implementation. The UI can change independent of the model. If the UI needs some particular new data then it will be added to a resource or if appropriate a new type of resource will be created. If a resource changes, it’s URL renamed or is removed it will likely break existing UI. To me this is the nature of applications. This is why the first option above (the details page knowing how to create the data URL) seems OK to me.
It may be better if the data resource described how to create the URL. It could provide the full URL for the benefit of the assumed generic clients and in addition provide a pattern plus the identifying parts. For example: rel = details, url = /api/accounts/083249, pattern = /api/accounts/*, id = 083249. The trouble is that the description is most efficiently given in the data resource providing the link (/api/accounts) but it is needed by the UI account details page.
It is pointless to have an API, RESTful or otherwise, without some client but is the arbitrary client a myth? I think it depends on the generality of the API. Clearly the Amazon S3 service is very general and can be used by many different kinds of clients. If the data resources come about as part of building a specific web application then they are probably very specific to that UI. While other clients are possible they would probably end up being similar to the original web app or require changes to the data resources. This is a case of different UIs having different needs of its data model.
Is there a general client — one that can consume in a useful way my REST API as well as yours? For this to work the client and services would have to have a shared understanding of some content type. For the client to provide a UI the content type would need to declare the UI. There is such a client and content type. Its the web browser and HTML. Now we have come full circle and can see the problems. HTML has not kept up with the demands of rich efficient user interactions and does not allow separation of the view and model. HTML 5 and XForms may be addressing these issues. (I have only read parts of the HTML 5 Draft and its been a long time since I read XForms.) Should HTML be providing a rich set of built in functionality or a minimal set that can be composed with scripting to accomplish the desired rich interaction? Going back to my HTML is the assembly language of the web analogy, do we want a CISC or RISC architecture?
How are you creating RESTful web apps today?