BT
x Your opinion matters! Please fill in the InfoQ Survey about your reading habits!

REST Anti-Patterns

Posted by Stefan Tilkov on Jul 02, 2008 |

When people start trying out REST, they usually start looking around for examples – and not only find a lot of examples that claim to be “RESTful”, or are labeled as a “REST API”, but also dig up a lot of discussions about why a specific service that claims to do REST actually fails to do so.

Why does this happen? HTTP is nothing new, but it has been applied in a wide variety of ways. Some of them were in line with the ideas the Web’s designers had in mind, but many were not. Applying REST principles to your HTTP applications, whether you build them for human consumption, for use by another program, or both, means that you do the exact opposite: You try to use the Web “correctly”, or if you object to the idea that one is “right” and one is “wrong”: in a RESTful way. For many, this is indeed a very new approach.

The usual standard disclaimer applies: REST, the Web, and HTTP are not the same thing; REST could be implemented with many different technologies, and HTTP is just one concrete architecture that happens to follow the REST architectural style. So I should actually be careful to distinguish “REST” from “RESTful HTTP”. I’m not, so let’s just assume the two are the same for the remainder of this article.

As with any new approach, it helps to be aware of some common patterns. In the first two articles of this series, I’ve tried to outline some basic ones – such as the concept of collection resources, the mapping of calculation results to resources in their own right, or the use of syndication to model events. A future article will expand on these and other patterns. For this one, though, I want to focus on anti-patterns – typical examples of attempted RESTful HTTP usage that create problems and show that someone has attempted, but failed, to adopt REST ideas.

Let’s start with a quick list of anti-patterns I’ve managed to come up with:

  1. Tunneling everything through GET
  2. Tunneling everything through POST
  3. Ignoring caching
  4. Ignoring response codes
  5. Misusing cookies
  6. Forgetting hypermedia
  7. Ignoring MIME types
  8. Breaking self-descriptiveness

Let’s go through each of them in detail.

Tunneling everything through GET

To many people, REST simply means using HTTP to expose some application functionality. The fundamental and most important operation (strictly speaking, “verb” or “method” would be a better term) is an HTTP GET. A GET should retrieve a representation of a resource identified by a URI, but many, if not all existing HTTP libraries and server programming APIs make it extremely easy to view the URI not as a resource identifier, but as a convenient means to encode parameters. This leads to URIs like the following:

http://example.com/some-api?method=deleteCustomer&id=1234

The characters that make up a URI do not, in fact, tell you anything about the “RESTfulness” of a given system, but in this particular case, we can guess the GET will not be “safe”: The caller will likely be held responsible for the outcome (the deletion of a customer), although the spec says that GET is the wrong method to use for such cases.

The only thing in favor of this approach is that it’s very easy to program, and trivial to test from a browser – after all, you just need to paste a URI into your address bar, tweak some “parameters”, and off you go. The main problems with this anti-patterns are:

  1. Resources are not identified by URIs; rather, URIs are used to encode operations and their parameters
  2. The HTTP method does not necessarily match the semantics
  3. Such links are usually not intended to be bookmarked
  4. There is a risk that “crawlers” (e.g. from search engines such as Google) cause unintended side effects

Note that APIs that follow this anti-pattern might actually end up being accidentally restful. Here is an example:

http://example.com/some-api?method=findCustomer&id=1234

Is this a URI that identifies an operation and its parameters, or does it identify a resource? You could argue both cases: This might be a perfectly valid, bookmarkable URI; doing a GET on it might be “safe”; it might respond with different formats according to the Accept header, and support sophisticated caching. In many cases, this will be unintentional. Often, APIs start this way, exposing a “read” interface, but when developers start adding “write” functionality, you find out that the illusion breaks (it’s unlikely an update to a customer would occur via a PUT to this URI – the developer would probably create a new one).

Tunneling everything through POST

This anti-pattern is very similar to the first one, only that this time, the POST HTTP method is used. POST carries an entity body, not just a URI. A typical scenario uses a single URI to POST to, and varying messages to express differing intents. This is actually what SOAP 1.1 web services do when HTTP is used as a “transport protocol”: It’s actually the SOAP message, possibly including some WS-Addressing SOAP headers, that determines what happens.

One could argue that tunneling everything through POST shares all of the problems of the GET variant, it’s just a little harder to use and cannot explore caching (not even accidentally), nor support bookmarking. It actually doesn’t end up violating any REST principles so much – it simply ignores them.

Ignoring caching

Even if you use the verbs as they are intended to be used, you can still easily ruin caching opportunities. The easiest way to do so is by simply including a header such as this one in your HTTP response:

Cache-control: no-cache

Doing so will simply prevent caches from caching anything. Of course this may be what you intend to do, but more often than not it’s just a default setting that’s specified in your web framework. However, supporting efficient caching and re-validation is one of the key benefits of using RESTful HTTP. Sam Ruby suggests that a key question to ask when assessing somethings RESTfulness is “do you support ETags”? (ETags are a mechanism introduced in HTTP 1.1 to allow a client to validate whether a cached representation is still valid, by means of a cryptographic checksum). The easiest way to generate correct headers is to delegate this task to a piece of infrastructure that “knows” how to do this correctly – for example, by generating a file in a directory served by a Web server such as Apache HTTPD.

Of course there’s a client side to this, too: when you implement a programmatic client for a RESTful service, you should actually exploit the caching capabilities that are available, and not unnecessarily retrieve a representation again. For example, the server might have sent the information that the representation is to be considered “fresh” for 600 seconds after a first retrieval (e.g. because a back-end system is polled only every 30 minutes). There is absolutely no point in repeatedly requesting the same information in a shorter period. Similarly to the server side of things, going with a proxy cache such as Squid on the client side might be a better option than building this logic yourself.

Caching in HTTP is powerful and complex; for a very good guide, turn to Mark Nottingham’s Cache Tutorial.

Ignoring status codes

Unknown to many Web developers, HTTP has a very rich set of application-level status codes for dealing with different scenarios. Most of us are familiar with 200 (“OK”), 404 (“Not found”), and 500 (“Internal server error”). But there are many more, and using them correctly means that clients and servers can communicate on a semantically richer level.

For example, a 201 (“Created”) response code signals that a new resource has been created, the URI of which can be found in a Location header in the response. A 409 (“Conflict”) informs the client that there is a conflict, e.g. when a PUT is used with data based on an older version of a resource. A 412 (“Precondition Failed”) says that the server couldn’t meet the client’s expectations.

Another aspect of using status codes correctly affects the client: The status codes in different classes (e.g. all in the 2xx range, all in the 5xx range) are supposed to be treated according to a common overall approach – e.g. a client should treat all 2xx codes as success indicators, even if it hasn’t been coded to handle the specific code that has been returned.

Many applications that claim to be RESTful return only 200 or 500, or even 200 only (with a failure text contained in the response body – again, see SOAP). If you want, you can call this “tunneling errors through status code 200”, but whatever you consider to be the right term: if you don’t exploit the rich application semantics of HTTP’s status codes, you’re missing an opportunity for increased re-use, better interoperability, and looser coupling.

Misusing cookies

Using cookies to propagate a key to some server-side session state is another REST anti-pattern.

Cookies are a sure sign that something is not RESTful. Right? No; not necessarily. One of the key ideas of REST is statelessness – not in the sense that a server can not store any data: it’s fine if there is resource state, or client state. It’s session state that is disallowed due to scalability, reliability and coupling reasons. The most typical use of cookies is to store a key that links to some server-side data structure that is kept in memory. This means that the cookie, which the browser passes along with each request, is used to establish conversational, or session, state.

If a cookie is used to store some information, such as an authentication token, that the server can validate without reliance on session state, cookies are perfectly RESTful – with one caveat: They shouldn’t be used to encode information that can be transferred by other, more standardized means (e.g. in the URI, some standard header or – in rare cases – in the message body). For example, it’s preferable to use HTTP authentication from a RESTful HTTP point of view.

Forgetting hypermedia

The first REST idea that’s hard to accept is the standard set of methods. REST theory doesn’t specify which methods make up the standard set, it just says there should be a limited set that is applicable to all resources. HTTP fixes them at GET, PUT, POST and DELETE (primarily, at least), and casting all of your application semantics into just these four verbs takes some getting used to. But once you’ve done that, people start using a subset of what actually makes up REST – a sort of Web-based CRUD (Create, Read, Update, Delete) architecture. Applications that expose this anti-pattern are not really “unRESTful” (if there even is such a thing), they just fail to exploit another of REST’s core concepts: hypermedia as the engine of application state.

Hypermedia, the concept of linking things together, is what makes the Web a web – a connected set of resources, where applications move from one state to the next by following links. That might sound a little esoteric, but in fact there are some valid reasons for following this principle.

The first indicator of the “Forgetting hypermedia” anti-pattern is the absence of links in representations. There is often a recipe for constructing URIs on the client side, but the client never follows links because the server simply doesn’t send any. A slightly better variant uses a mixture of URI construction and link following, where links typically represent relations in the underlying data model. But ideally, a client should have to know a single URI only; everything else – individual URIs, as well as recipes for constructing them e.g. in case of queries – should be communicated via hypermedia, as links within resource representations. A good example is the Atom Publishing Protocol with its notion of service documents, which offer named elements for each collection within the domain that it describes. Finally, the possible state transitions the application can go through should be communicated dynamically, and the client should be able to follow them with as little before-hand knowledge of them as possible. A good example of this is HTML, which contains enough information for the browser to offer a fully dynamic interface to the user.

I considered adding “human readable URIs” as another anti-pattern. I did not, because I like readable and “hackable” URIs as much as anybody. But when someone starts with REST, they often waste endless hours in discussions about the “correct” URI design, but totally forget the hypermedia aspect. So my advice would be to limit the time you spend on finding the perfect URI design (after all, their just strings), and invest some of that energy into finding good places to provide links within your representations.

Ignoring MIME types

HTTP’s notion of content negotiation allows a client to retrieve different representations of resources based on its needs. For example, a resource might have a representation in different formats such as XML, JSON, or YAML, for consumption by consumers implemented in Java, JavaScript, and Ruby respectively. Or there might be a “machine-readable” format such as XML in addition to a PDF or JPEG version for humans. Or it might support both the v1.1 and the v1.2 versions of some custom representation format. In any case, while there may be good reasons for having one representation format only, it’s often an indication of another missed opportunity.

It’s probably obvious that the more unforeseen clients are able to (re-)use a service, the better. For this reason, it’s much better to rely on existing, pre-defined, widely-known formats than to invent proprietary ones – an argument that leads to the last anti-pattern addressed in this article.

Breaking self-descriptiveness

This anti-pattern is so common that it’s visible in almost every REST application, even in those created by those who call themselves “RESTafarians” – myself included: breaking the constraint of self-descriptiveness (which is an ideal that has less to do with AI science fiction than one might think at first glance). Ideally, a message – an HTTP request or HTTP response, including headers and the body – should contain enough information for any generic client, server or intermediary to be able to process it. For example, when your browser retrieves some protected resource’s PDF representation, you can see how all of the existing agreements in terms of standards kick in: some HTTP authentication exchange takes place, there might be some caching and/or revalidation, the content-type header sent by the server (“application/pdf”) triggers the startup of the PDF viewer registered on your system, and finally you can read the PDF on your screen. Any other user in the world could use his or her own infrastructure to perform the same request. If the server developer adds another content type, any of the server’s clients (or service’s consumers) just need to make sure they have the appropriate viewer installed.

Every time you invent your own headers, formats, or protocols you break the self-descriptiveness constraint to a certain degree. If you want to take an extreme position, anything not being standardized by an official standards body breaks this constraint, and can be considered a case of this anti-pattern. In practice, you strive for following standards as much as possible, and accept that some convention might only apply in a smaller domain (e.g. your service and the clients specifically developed against it).

Summary

Ever since the “Gang of Four” published their book, which kick-started the patterns movement, many people misunderstood it and tried to apply as many patterns as possible – a notion that has been ridiculed for equally as long. Patterns should be applied if, and only if, they match the context. Similarly, one could religiously try to avoid all of the anti-patterns in any given domain. In many cases, there are good reasons for violating any rule, or in REST terminology: relax any particular constraint. It’s fine to do so – but it’s useful to be aware of the fact, and then make a more informed decision.

Hopefully, this article helps you to avoid some of the most common pitfalls when starting your first REST projects.

Many thanks to Javier Botana and Burkhard Neppert for feedback on a draft of this article.

Stefan Tilkov is the lead editor of InfoQ’s SOA community and co-founder, principal consultant and lead RESTafarian of Germany/Switzerland-based innoQ.

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread
Community comments

Great Points; Here's Another... by Ray Krueger

I think this probably ties into your "Tunneling through GET" point. I've seen a few applications with interfaces like this...
example.com/someNoun?xml={url encoded xml goes here}
and
example.com/someOtherNoun?json={url encoded json goes here}


It seems akin to "Tunneling Messaging Through GET"...

Great stuff, be good to read more by Colin Jack

Really good stuff, I've been reading a lot about REST recently and this is exactly the sort of content that is needed for people like me who are only now looking into the topic in detail.

In fact its so good that I think it would be useful if (at some point) there were further articles that could go into detail on some of the aspects you cover, in particular "Breaking self-descriptiveness" and "Forgetting hypermedia". Personally I found that initially these aspects of REST were initially difficult to grasp.

I was also wondering whether you were aware of an existing REST reference application, particular one that covers an enterprise application?

Re: Great stuff, be good to read more by Stefan Tilkov

Thanks Colin. The only attempt at an enterprise application reference implementation is Joe Gregorio's REST DayTrader variant. Any suggestion what other enterprise app could be used as an example would be greatly appreciated.

Can you expand a bit? by Karl Krukow

Hello Stefan,


Thanks for another great article — I am looking forward to the future ones that will go more in depth.


I was wondering about two of your points:


Point 5. “misusing cookies” - As you mention, the usual way of performing authentication in web applications is to assign a session id to each fresh request, keep this as a cookie and then store session information at the server which says, e.g., the session id is authenticated and corresponds to user X. You seem to argue that the restful approach would be to avoid this and use e.g. HTTP Basic or Digest authentication, is this correct? At first thought this seems impractical… What would you say? In practice what would you do for your ‘common-case ajax web-app’?


Point 6. Hypermedia. I like this principle, but I’m wondering about the consequences of taking this approach to the extreme. Often you want composite or ‘aggregate’ representation of resources. For example, a user might have a userprofile and account information, etc. If you want a representation of this user, say in a web-app, you often want a page composing username (a property of the user resource) with adress (say userprofile) and account number (account resource information). You can fetch the user resource which links to it’s user profile which may in turn link to the account. In this approach, being REST compliant entails many more HTTP request than a single aggregate i.e., non-hypermedia based approach.


In general suppose you want a summary view of a collection resource. You can represent your collection as a list of links to the individual resources, or you can aggregate the collection to one large response. If you do the former, you potentially have n requests where a single would be enough. It reminds me of the n+1 problem for databases...


Of course you may argue the other way around, but the discussion is still valid.


What is your opinion on this? It it better to create a new aggregate resource specifically for this purpose?


Thanks,
Karl

Re: Can you expand a bit? by Stefan Tilkov

Thanks Karl. Adressing your first point: Wherever possible, I would indeed suggest using HTTP authentication instead of cookies. But even if you use cookies, it's perfectly fine to do so if you avoid session state. The way to do this is to encode a token, in the cookie that the server can validate without session state. Aristotle Pagaltzis recently summarized how to do this in a discussion in the Yahoo! rest-discuss group:

Regarding your second point: if I understand you correctly, you want to use aggregate resources. This is fine, and I don't see a conflict with hypermedia. On the contrary, you can actually include links to the details view and back, offering your users to navigate into the direction that's more appropriate for them.



auth_token = concat( username, ":", expiration_datetime );
msghash = digest_hmac( concat( server_secret, ":", auth_token ) );
cookie = concat( msghash, ":", auth_token );


Rails 2.1 uses a similar approach, but encodes "session" state (which is really client state) in the cookie – a practice I don't really like that much, but would claim is RESTful nonetheless.

tunneling through POST by Bryan Taylor

Regarding tunneling through POST, you wrote "It actually doesn’t end up violating any REST principles so much – it simply ignores them."



This is interesting, and it echos a point I've made: if I do SOAP and I as the service designer I'm not able or willing to declare any of my operations permanently "safe", then the HTTP spec tells me I SHOULD use POST, and I'm not certainly not violating any principle of REST. I'd certainly agree it's not in the "spirit" of REST, which wants me to introduce safe resources for most of my "nouns", but does SOAP violate any objective principle of REST? I think it's just not idiomatic, but at this point it's not an objective, technical criteria but a subjective, artistic one. When discussing the GoF patterns, I don't think there's much artistic interpretation that goes on to know if I have a factory pattern, strategy pattern, command pattern, or whatever. Does REST boil down to "I know it when I see it".



If I look at SOAP as a way to send a message to a method of a some kind of virtual object ("Simple Object Access Protocol", after all), the fact that object behavior is encapsulated means that I, as the web service builder and a client of underlying class, don't know if the method is safe or not because it doesn't tell me that it is. It could be getPurchaseOrder(), but I really don't know if this is an idempotent operation. Often it is, but I can't guarantee that it is without some kind of language semantics like some kind of @Safe annotation (which doesn't exist to my knowledge). Absent something like this, isn't POST the only reasonable thing to use? Even if I know the base implementation class uses a safe implementation, a runtime instance could polymorph this safe behavior into something that's not safe, right?



Anyway, it seems that the real idiomatic difference is between REST and OO, not just REST and SOAP. I'd like to understand what it is about the web that makes REST a "nicer" programming paradigm than OO. Conversely, why not apply REST everywhere, like say in the programming language itself. Imagine that Object declares get(), put(), post(), and delete() and is final. Imagine a uri scheme object:// instead of references. Would anybody use this language? It'd certainly simplify my javadocs :)

The real challenge is letting go of services/methods by Jakub Nešetřil

Congratulations Stefan to a nice article. A lot of the patterns are really notorious - however, the one I find most frequented seems to be missing.



In my opinion, the real challenge is getting rid of the method-oriented afterthoughts of SOAP and RMI. In a certain way, RMI is compatible with anybody's programming style, just putting a network between the method invocations.



With REST where action is a result of state changes, you have to convince your colleagues to a mental paradigm shift to state-automatons or data-flow programming. That's the part I find really hard.

Re: tunneling through POST by Paul Beckford

Anyway, it seems that the real idiomatic difference is between REST and OO, not just REST and SOAP.


I use to think this, but it is another misconception. REST and true (late-bound) OO are very similar in fact. Think of the REST uniform connector idea as an object with a fixed protocol (fixed number of methods), and resources as parameters to those methods.

Using a "uniform connector" means that the client needs to know very little about the server (other than the server understands the uniform protocol). You can use the same technique with Objects if you wished (no need for final though), with the same effect of reduced coupling between the client and the server.

REST is a response to the problem of large scale application distribution. If I control both client and server in the same memory space then the constraint of a fixed uniform connector is no longer as appealing :)

Paul.

Question on "Ignoring status codes" by mani doraisamy

Thanks for another great article, Stefan.
Quick question on Ignoring status codes:
"For example, a 201 (“Created”) response code signals that a new resource has been created, the URI of which can be found in a Location header in the response."
Does this mean there has to be 2 requests: one to create and the other to read the content from the URI? Is this a feasible option for human consumption?

Re: Question on by Alexander Klimetschek

Does this mean there has to be 2 requests: one to create and the other to read the content from the URI? Is this a feasible option for human consumption?


201 Created is (mostly) used after a PUT to create a new resource. The target URL is typically a generic one (eg. /blogposts or /blogposts/*), since often the server builds the unique URL for the resource. The 201 confirms the creation and gives the client the information where the new resource can be found now.

Re: Question on "Ignoring status codes" by Craig McClanahan


Does this mean there has to be 2 requests


Expanding a bit on Alexander's response, this does not mean two requests. On the response to the "create" request, you return both the 201 "Created" status code, and an HTTP "Location:" header, whose value should be an absolute URL to the newly created resource.

Exposing Algorithms by Eric Larson

One pattern I've seem people follow is using query string parameters when the resource is exposing some sort of algorithm or dynamic representation. The thing to watch out for is that you do not define this pattern in terms of the algorithm or code producing the page, but rather the meaning to the user. For example, adding a "page=3" argument to something like a feed makes sense because you are asking for a slightly different representation of the resource. But, if you have a set of parameters describing the feed such as "tag=java" and "year=2008" then there is a good chance you are exposing an algorithm that would be better served as a simple resource.

Re: tunneling through POST by Erik Johnson

The extreme case of tunneling via POST through a single URI certainly has limited appeal. For one thing, it precludes the use of hypermedia links in content (they would all point to same URL).

That said, I don't see tunneling through POST as an automatic anti-pattern. For one thing, given the presence of an otherwise complete URI-space (with the requisite GET/PUT/etc. support), POST provides a way to multiplex operations. It isn't feasible to identify each potentially unique content-set and there are times when one round-trip is preferred :).

I just don't want to see POST==BAD become a conclusion without more thought put into it.

Re: Question on "Ignoring status codes" by mani doraisamy

Not sure if i explained the question correctly. I am talking about a usecase where the user hits a create button (for a new PurchaseOrder) and expects the browser to show up the created resource (i.e. PurchaseOrder). How would this usecase translate into REST calls?

Re: Question on "Ignoring status codes" by Stefan Tilkov

Unfortunately, browsers don't follow the "Location" header sent back with a 201 (I don't really have any idea why). To avoid re-submitting, common practice is to send a redirect to the new resource after POST, which will make the browser issue a GET to it.

Re: Question on "Ignoring status codes" by mani doraisamy

I assume that redirection means 2 requests from browser:

1) create (or any action) request - as POST

2) redirection request to get the resource - as GET.



While most of the MVC frameworks will return the view after the action in a single request. Is this the cost we have to pay for a cleaner architecture? Or is there a better way?

Re: tunneling through POST by Bryan Taylor

When you say "tunneling via POST through a single URI certainly has limited appeal", I ask appeal to who? Certainly there are a lot of enterprises deploying SOAP on a large scale that do exactly that. If you had said it's not idiomatic for REST, then certainly you'd be right.

I just wonder whether or not embedded URIs and the concept of "hypermedia as the engine of application state" is really a human usability thing. If the consumer is code, I don't see any particular benefit. If you have account_id="123" embedded vs an actual account URI the client can actually use this in a more flexible way, where it and not the server decides where it wants to go next. Doesn't HATEOAS actually increase the burden on the server to completely define the workflows that use it's resources as state transitions it supports via links? I'm not saying that is good or bad, just that it is a constraint that many systems, especially in enterprise settings will not be capable of conforming to. I have no doubt that when you can meet that constraint, I do see many benefits that will flow from it.

Re: tunneling through POST by Paul Beckford

Hi Bryan,

Maybe I was too subtle in my last response, but REST actively avoids RPC (SOAP) since it encodes application specific behaviour (operations) in the connector interface itself. This means that each time the behaviour of your server changes so does the interface and hence all clients must change too. This approach is brittle causing you to recompile your client with new a new stub. With a uniform connector and a self describing resource with hyperlinks, then you can represent application state as additional resources which are accessible through links. You can add or delete links as you like exposing and hiding state without braking the uniform connector interface.

In Roy Fieldings dissertation he goes through a number of client server architectural styles and lists the pros and cons for each. If high dependency between client and server is not a problem then an alternative to REST (like RPC) may be your best bet. The success of the web is that it avoids such coupling which means that it can evolve and change without ever needing to recompile the client (browser). This is where REST excels.

Re: Question on by Stefan Tilkov


I assume that redirection means 2 requests from browser:
1) create (or any action) request - as POST
2) redirection request to get the resource - as GET.


There is no reason at all a framework would have to do all actions via POST, so in many cases, a single request is fine. When a POST is used, there should be a redirect simply to avoid the warning when a user hits "refresh", and to support bookmarking. Things would be much better if browsers supported PUT and DELETE and followed Location headers in 201 responses - but sadly, they don't.

great stuff! by James Strachan

Awesome article Stefan - you've definitely nailed most of the anti-patterns folks tend to hit in my experience. REST is definitely one of those things some folks think they are being RESTful because they use some GET and maybe some POST - articles like this really help to clarify things.

The only other grey areas of REST I've seen that are not mentioned (but are kinda tiny nits really) are...

* no easy way to associate XSDs with MIME types for XML representations - there seems to be a few different ways folks try this hacking the MIME type for example. We could maybe do with some kinda standardised way to associate metadata more easily; maybe the AtomPub service document idea or something WADLish. Though given JSON tends to be easier than XML - maybe this isn't such a biggie :)

* using URIs instead of accept content-type headers to influence the representation. Most good frameworks tend to have a convention where you can, say, append ".xml" or ".json" or ".yaml" or whatever to force the representation without having to specify accept headers. While a bit of a hack it is kinda handy allowing folks to use any browser to view different representations - without relying on custom plugins in browsers etc. It might be nice to kinda standardise this kinda stuff.

But those are tiny nits - these 10 anti-patterns are right on the money! Keep it up! :)

We seem to have similar timing ;) by Benjamin Carlyle

I was mulling over the phrase "REST Patterns" as it was coming up as a training need in my office. I'm focusing on patterns for machine-to-machine communication, but have started to collect a few myself: REST Patterns @ soundadvice.id.au



I have quite a bit more work to do, and I still have to clear up some cloudy IP issues before I am able to get out my complete list :-/

Re: tunneling through POST by Bryan Taylor

SOAP uses a rich (non-uniform) interface, because that's what you do when you program with objects, and SOAP tries to mimick this. So you're argument for the uniform interface is really one against object oriented programming generally, as you haven't told me any web specific reason to necessitate the switch of architectural style. Somehow I don't think object oriented coding would be as popular and successful if it was as brittle as you say something without the uniform interface must be.



I also have to question the idea that RESTful resources are normally "self describing". In fact, this is a key weakness of REST that presently prevents widespread adoption of in enterprise settings (at least until WADL or WSDL 2.0 gain more traction there). The idea that you won't have to redeploy a new client if the server behavior changes in REST is a bit far fetched for the same reason. The fact that hypermedia has embedded URIs doesn't mean that client code knows how to translate these URI into a semantic meaning, nor does it protect the client from having to be changed if new state transitions are added or others are taken away. Application code must understand the interchange format in detail. REST gives you no way to say anything more descriptive than the media-type such as "application/xml". When I do a GET, I may discover that I don't understand the payload or that it's changed from what my client code supports. The wonderful state machine via links is then useless to me. Without service descriptions, such changes happen without warning at runtime and break things, even if I got to the /account/1234 doc by following HATEOUS navigations. Moreover, if I'm a client constructing a POST or a PUT, I don't even have the benefit of an example. I have no way to know what the payload I should construct must look like, other than XML.

Re: tunneling through POST by Benjamin Carlyle

Brian,


It is probably best to avoid emotive words like "rich" when comparing REST to the classical O-O style. A fairer comparison might be "unconstrained" (OO) vs uniform (REST).


REST and O-O are closely related. They are both typically client/server request/response messaging paradigms. The client has a reference to the server, and sends it a message. REST is a constrained form of O-O for systems with appreciable network latency, bandwidth constraints, a number of different owners and different release cycles for different components of the architecture.


Perhaps the clearest contrast is between REST and a strongly-typed O-O language. In nice, crinkly java I get a compile error whenever two components disagree on the definition of an interface. The client tries to call method foo. There is no method foo. Bail. In this setting it makes sense to leverage the strongly-typed nature of the language to make sure you don't release junk. You define interfaces in a detailed and domain-specific way that is checked to yield a consistent releasable whole.


In REST, I want the client or the server I deployed literally 10 years ago to work with whatever I am putting out today. I also want whatever I'm putting out today to work with every bit of code written since that time, and every bit of code that will be written in the next 10 years. Getting more specific than necessary is a sub-optimal approach in this environment. There is no compiler to lean on to ensure consistency, and there is no way you could "fix" the old deployed code to work with your latest and greatest. Instead, we lean less on checking and more on uniformity. You don't want to call out thirty or forty versions of an interface that you adapted as your needs changed, and provide explicit support for each. You want something generic, stable and slightly sloppy.


It's not a matter of REST rejecting O-O, or for that matter replacing O-O. It's a matter of different contexts. The growing importance of REST is a recognition that the important bit of software architecture is moving away from "how do I get a release of my project out" to "how do I get my system to work with the other 15 business systems either deployed or in the process of being deployed? How do I future-proof this system in face of constant change?"



To answer your points: Yes, we need better descriptions of what specific URLs are going to do with our PUT and GET requests. Whether that is a matter of producing more machine-readable content or simply more human-readable content is still up for grabs. Yes, we need better document types... the kinds of document types you only come up with by solving real problems. No, I don't think the REST community is at the tipping point where they are solving these problems well enough. I'm hoping they'll/we'll be there soon. At least we know that document-oriented SOA is in the same boat with some of our problems.



See also my GET pattern description. I welcome feedback on this and other pattern descriptions.



Benjamin.

Re: PUT, POST, and URIs for creating new resources by Markus Krüger

201 Created is (mostly) used after a PUT to create a new resource. The target URL is typically a generic one (eg. /blogposts or /blogposts/*), since often the server builds the unique URL for the resource. The 201 confirms the creation and gives the client the information where the new resource can be found now.


If you're using PUT, you should use the specific URL the resource should be stored under, not some generic URL. If you want to create a new resource without specifying the resource URL, the API should use POST instead of PUT.

From RFC 2616, chapter 9.6:

The fundamental difference between the POST and PUT requests is
reflected in the different meaning of the Request-URI. The URI in a
POST request identifies the resource that will handle the enclosed
entity. That resource might be a data-accepting process, a gateway to
some other protocol, or a separate entity that accepts annotations.
In contrast, the URI in a PUT request identifies the entity enclosed
with the request -- the user agent knows what URI is intended and the
server MUST NOT attempt to apply the request to some other resource.
If the server desires that the request be applied to a different URI,
it MUST send a 301 (Moved Permanently) response; the user agent MAY
then make its own decision regarding whether or not to redirect the
request.

Re: Question on "Ignoring status codes" by Sebastian Kirsch

I assume that redirection means 2 requests from browser:

1) create (or any action) request - as POST

2) redirection request to get the resource - as GET.



While most of the MVC frameworks will return the view after the action in a single request. Is this the cost we have to pay for a cleaner architecture? Or is there a better way?

I always assumed that if a PUT is processed successfully, the server should respond with

1) a 201 SC

2) the representation of the created resource as it would be returned by serving a GET request



Referring to Markus' comment, I'd agree that a PUT affects the addressed resource and thus there should be no need for a location header - though it makes great sense when using POST to create resources.



Another thing I'd expect to find in a PUT response is caching information: expires header, etag and - here I contradict myself - maybe even the location header, as I wouldn't rely on a proxy/gateway to cache things if that header isn't present.

Why? The proxy/gateway should then be able to serve a plain GET request for that resource without forwarding the request to the server even once.

"ephimeral" resources by martin sarsale

First of all, great article. Your checklist works pretty good against my API implementation, but I was missing Hyperlinking, which makes a lot of sense.

This is a more open question, which maybe fits better in a forum. Anyway, here it goes:

I'm kind of puzzled on how to expose "ephimeral" resources, for example, the output of a search. I understand the search results are 'a resource' but I'm wondering if there's any rule to create URLs for those.

for example,

api.foo.com/search/foo+bar/

and, what happens with paginated searches. Do you like this:

api.foo.com/search/foo+bar/1

I would love to use "Content-range" but I think it's forcing things a little bit :)

Anyway, really enjoyed the article.

Re: Great stuff, be good to read more by Colin Jack

Thanks for the link, really good content. I'll try to think of a good example but this one gave me a lot of good information.

Re: Question on "Ignoring status codes" by Matthias W

I always assumed that if a PUT is processed successfully, the server should respond with
1) a 201 SC
2) the representation of the created resource as it would be returned by serving a GET request

Not necessarily. REST also allows PUT for updating complete existing resources. Therefore, a 200 SC (or, more common, a 204 No Content) may be more appropriate, depending on the existence of the targeted resource.

Re: Great stuff, be good to read more by Colin Jack

Stefan, I think the travel agency service from CH10 in "RESTful Web Services" would be a good example.

I actually think the authors missed a trick not exploring the travel agency application in more detail. Not to say social bookmarking examples aren't interesting but really I think most examples of services that "have a different grain than the rest of the Web" would be useful.

Another Example for a "REST API" that isn't really RESTful? by Eike Herzbach

Here help.launchpad.net/API it says:
The service is designed around the principles of REST, with the goals of simplicity and transparency.

When looking into the documentation, you find stuff like
Custom POST methods:
acceptInvitationToBeMemberOf
addMember
declineInvitationToBeMemberOf

What are your thoughts about this?

Re: Another Example for a by Stefan Tilkov

Without having taken a closer look, this seems to show either a misunderstanding of REST or unwillingness to label things correctly :-) It seems like a classical example of POST tunneling.

Re: Question on by Alex Popescu

201 Created is (mostly) used after a PUT to create a new resource. The target URL is typically a generic one (eg. /blogposts or /blogposts/*), since often the server builds the unique URL for the resource. The 201 confirms the creation and gives the client the information where the new resource can be found now.


I might be wrong about it, but I was having the impression that PUT requests are (required to) providing the new/updated resource identifier and what you are explaining applies in fact to POST.

./alex

Re: Question on by Alex Popescu

It looks like Markus is agreeing with my point in the next comment :-).

./alex

Re: Can you expand a bit? by Valko Yotov

Hi Stefan,

great article, but about the authentication, if you store anything like server_secret on the server like Aristotle Pagaltzis suggests:

"Aside from the server secret, which is easily kept in memory,
you do not need any information external to the cookie in order
to verify it: no on-disk session."

what will happen with scallability? Storing in server memory is even worst from storing on-disk for that purposes. You will have in fact server memory session then?

Re: Can you expand a bit? by Stefan Tilkov

Hi Valko, I'm not sure whether this is a misunderstanding: the server secret is just a single value, such as a string, that exists once per server or server cluster. It's easily kept in configuration, or grabbed from a common service resource during server startup.

Re: Question on by Mike Pearce

If you're creating the resource in the first place with either a PUT or a POST, why would you then need to GET the resource afterwards? Surely you'd have the data available to you?

But, yes, you'd need to do two HTTP requests; the second would be a GET to a URI that was provided as a link in the body of the PUT response. But this will have a useful byproduct if you've got caching enabled as subsequent calls to the resource URI would be cached.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

36 Discuss

Educational Content

General Feedback
Bugs
Advertising
Editorial
InfoQ.com and all content copyright © 2006-2014 C4Media Inc. InfoQ.com hosted at Contegix, the best ISP we've ever worked with.
Privacy policy
BT