Skip to content

Your Web Service Might Not Be RESTful If…

The other day, I gave a brief talk about our HTTP Library, Resourceful. After a few minutes of going over the features, it became apparent to me that very few people have taken the time to appreciate the finer points of HTTP. Everyone who calls themself a web application developer needs to take a few hours to read RFC2616: Hypertext Transfer Protocol — HTTP/1.1. Its not very long, and increadibly readable for a spec. Print it out, and read a few sections when you go for your morning “reading library” break. Unfortunately, a great many people got confused by it, and ended up reimplementing a lot of http in another layer, and thats how we ended up with SOAP and XML-RPC. There’s a good parable about how this all went of the rails for awhile, until some people re-discovered a section in Roy T. Fielding’s disseration, “Representational State Transfer (REST)“.

Needless to say, REST is making a huge comeback, at least in the agile startup communities. It’s fast, lightweight, and easy to put together. Ruby on Rails even has excellent support for getting up and running quicky. Sadly, though, it’s not quite right, and as a result, developers have misconstrued REST yet again, and its making things harder than they really need to be, and also leading them down a path that leads to lots of headaches in the future. If you’re interested in learning more about REST, there’s plenty of excellent resources on the REST Wiki, particularly REST In Plain English.

For some of my examples, I’m going to pick on the Pivotal Tracker “RESTful” API. Sorry guys, I needed to pick someone, and I love your product (I use it every day), but you’re part of the reason for this post. I wanted to write a client for your service, but its really much harder than it needs to be. The service violates many of the constraints of REST, and therefore naming it “RESTful” is incorrect. You’re not the only ones, though, so don’t feel bad, nearly EVERY API that claims to be RESTful isn’t. For a look at one that gets it (mostly) right, check out Netflix.

If Your Web Services Do Any of These Things, You’re Doing it Wrong

  1. Clients have to read documentation to know the locations of top-level resources.
  2. Clients have to concatenate strings to get to the next resource.
  3. You have an “API/Key/Token” in a header or a url.
  4. You have a version string in a url.

1. Have a Minimum of Starting Points

If you look at the Available Actions on Pivotal Tracker’s API page, you’ll see they list several actions that can be performed. This isn’t REST, this is XML-RPC. Nearly everybody gets this one wrong. Due to the amount of confusion, Roy Fielding published a post to stop people abusing the term “RESTful” and to try and clarify what a real RESTful API is. His final point is:

A REST API should be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types that are appropriate for the intended audience (i.e., expected to be understood by any client that might use the API).

The point here is that there should be only one resource that is the starting point for any interaction with the service. This is called a “well-known” resource, and is never, ever allowed to change locations. If it does change, you break every single client out there. By publishing a dozen or more well-known resources in their API docs, Tracker is no longer permitted to change any of them. This increases the maintenance burden, because now they have to maintain all these resources for the lifetime of the application, or deprecate any third-party clients.

If they had instead added a single resource that described the locations of these other resources, they would have much more flexibility in the future. An example of the content of such a resource:

<?xml version="1.0" encoding="UTF-8"?>
<services>
  <service>
    <name>AllProjects</name>
    <href>http://www.pivotaltracker.com/services/projects</href>
  </service>
  <service>
    <name>AllActivities</name>
    <href>http://www.pivotaltracker.com/services/activites</href>
  </service>
</services>

Note: Yes, they list several other actions on their API. However, each of them violates another one of the REST constraints, so I have ommitted them for the time being.

Now every client just needs to know the name of the resource they’re looking for, eg “AllActivites”, and they can continue as before. If, for some perfectly valid reason, Pivotal decides to change the name of “Activites” to, say, “Actions”, they only have to modify the href of the “AllActivities” service description, add a “AllActions” service, and every single client using it by the name instead of a hardcoded href continues to work flawlessly, or at least as well as it did before. Less maintenance burden on the service developers, and no burden at all for the developer of a well-written client.

2. Don’t Make a Client Construct URIs

In that very same bullet point, Roy continues…

From that point on, all application state transitions must be driven by client selection of server-provided choices that are present in the received representations…

If you look at the Tracker API docs Available API Actions for projects, you’ll see “Single project” and “All my projects”. We already covered how to handle the “AllProjects” resource, an in the example above, we remove the “Single project” resource entirely. So how do you get to the resource for a single project? Simple, you follow its link in the “AllProjects” resource.

    <?xml version="1.0" encoding="UTF-8"?>
    <projects type="array">
      <project>
        <href>http://www.pivotaltracker.com/services/v2/projects/1</href>

        <id>1</id>
        <name>Sample Project</name>
        <iteration_length type="integer">2</iteration_length>
        <week_start_day>Monday</week_start_day>
        <point_scale>0,1,2,3</point_scale>

        <stories_href>http://www.pivotaltracker.com/services/v2/projects/1/stories?{-join|&|filter,limit,offset}</stories_href>
        <iterations_href>http://www.pivotaltracker.com/services/v2/projects/1/iterations</iterations_href>
        <activities_href>http://www.pivotaltracker.com/services/v2/projects/1/activities</activities_href>
      </project>
      <!-- ... -->
    </projects>

For a client to find a single project, they would know its name. They would GET the list of services, find “AllProjects” by name, GET the “href” provided, and look for the project “Sample Project” by name. They could then use the href attribute to obtain the single resource for the project. Additionally, we also have links to all the actions in the docs that required a PROJECT_ID in the url. To get the iterations or activities for a project, a client has to only locate the project, and follow the links.

You should also notice the part of the stories_href enclosed in {braces}. This is known as a URI Template, and is very handy. If you noticed in pivotals API docs, they had three ways of getting stories: All stories, stories by a filter, and stories by a limit and offset. I took the liberty of combining these into single href, using the template to describe the query parameters. A ruby client, using the Addressable::URI library, could fill out that uri like this:

template = Addressable::Template(stories_href)
template.expand({
  "filter" => 'label:"needs feedback" type:bug'
})

All these extra requests might seem like a rather long way of going about it, however, the advantages are immense:

Should Tracker become huge, and everybody and their grandmother starts using it to keep track of their development projects, Tracker could outstrip the load of a single database. Since it appears they are using AUTOINCREMENT id columns for the project id, sharding the projects table is going to be hard. However, if they were to start using UUID columns for project ids, then sharding is a whole lot less complicated. However, if they change the project id in the API, everyone’s clients break. If clients were to instead follow the href, they can do whatever they want to the id, and existing clients will have no trouble at all following.

But wait, it gets better. What happens if the service still isn’t fast enough, for any number of perfectly plausible reasons? Because they’re using hrefs, they can put anything they want there. Say they decide to shard the application servers, so every project with an odd-numbered id goes to www1.pivotaltracker.com, and everything even-numbered goes to www2.pivotaltracker.com. They just have to update the links, and everyone’s client continues working.

If all resources are specified like this, then a client can get to every resource from that one starting point. You are free to move, rename, and add resources as you desire, without making things complicated for your API clients. Less maintenance burden on you, and none on your users.

Don’t put an “API Token” in a custom header, or in the URIs

While there’s nothing technically un-RESTful about this, its still annoying to your clients. And unless you have a full-time security expert on your staff, you probably did it wrong, and its not nearly as secure as you think it is. It’s also vulnerable to man-in-the-middle attacks and replay attacks, unless you use SSL. And if you do use SSL, then you’ve thrown away one of the major advantages of HTTP, which is caching. Just about every HTTP server and proxy are able to handle caching, and if they operate to spec, they’re not allowed to cache SSL documents. I’ll get more into caching in a future blog post, just realize that it can be immensely beneficial to the performance of your application, and you’re going to want to do everything you can to facilitate that.

Luckily, you have a third option: HTTP Digest Authentication. Its been vetted by security professionals and time, and is almost certainly more secure than some secret key you’ve come up with. There are many varieties of Digest auth. The one most useful for RESTful web services uses an algorithm of “MD5-sess” and Quality of Protextion (qop) of “auth”. The MD5-sess algorithm allows for 3rd-party authentication services, and not requiring the server to maintain a plaintext copy of the users’ passwords. A qop of “auth” protects against chosen-plaintext cryptanalysis attacks, by having a counter incremented by the client, and a client-generated nonce. For a quick overview, Wikipedia has a good article, and be sure to check out the spec, [RFC2617]. Here’s a simple example to see whats going on. Client requests are denoted by >, with server responses <. This obviously isn’t the whole content, just the interesting bits.

> GET /

< HTTP/1.1 401 Authorization Required
< WWW-Authenticate: Digest 
                    qop="auth", 
                    realm="My RESTful Application", 
                    opaque="55dd3242dd79740cefb67528b983bc8e", 
                    algorithm=MD5-sess, 
                    nonce="MjAwOS0wNy0xOSAyMDozMToyOToxODQ2NjA6MjAxZjRiMjVjZjRiYTc0MDEwNWIwY2U2NWIxMGNjNj"

> GET /
> Authorization: Digest 
                 username="admin", 
                 qop="auth", 
                 realm="My RESTful Application", 
                 algorithm="MD5-sess",
                 opaque="55dd3242dd79740cefb67528b983bc8e", 
                 nonce="MjAwOS0wNy0xOSAyMDozMToyOToxODQ2NjA6MjAxZjRiMjVjZjRiYTc0MDEwNWIwY2U2NWIxMGNjNj", 
                 uri="/", 
                 nc=00000001, 
                 cnonce="Mjg5MDIz", 
                 response="1b8e5cdcd8d49ca65e3d6142567e44cf"

< HTTP/1.1 200 OK
< Authentication-Info: qop=auth, 
                       nc=00000001, 
                       cnonce="Mjg5MDIz", 
                       nextnonce=00000002

Digest auth works when the client make an initial request without any authentication info. The server responds with a 401, and provides a few parameters to the client in the WWW-Authenticate header. The realm is a string used to identify the application. The client uses MD5 to hash together their username, the realm and their password. This is referred to as HA1. When the user was created, the server did the same, and HA1 is what is stored in the database.

The client then generates a random string (the “client nonce” or cnonce) and increments a counter (”nonce counter” nc). It hashes method as an uppercase string (”GET”) and the URI (”/”) together to produce HA2. Finally, it hashes HA1, HA2, the nonce, nc, cnonce, and qop all together to arrive at response. It packages this all up into the Authorization header, and makes the request again. The server has all the information it needs (it stored the HA1 instead of the plaintext password) to hash the same parameters itself. If it arrives at the same response, then it knows the client knows the password for the user, and allows it to proceed.

Optionally, the server can provide an Authentication-Info header attached to the response. This provides enough information for the client to automatically authenticate for the next request, without having to get a 401 again. An alternative would be to just keep using the same nonce over and over, but this may be subject to replay attacks. The downside of this, though, is that the client cannot pipeline requests.

Don’t put the API version in the URI

Several web services (including Tracker’s) have uris that look like http://myapp.com/v1/projects or http://myapp.com/projects?v=2. While this is perfectly RESTful, it seems a bit odd. From a pedantically REST-view, /v1/projects/1234 and /v2/projects/1234 are the locations of totally different resources, when, in fact, they are simply different representations of the same resource. From a more practical standpoint, say a client is written when only version one of a service is available, and it stores (”bookmarks”) some of these resources. Some time later, the application team decides they need to release some incompatible changes to their API, so they increment the version. Some time after that, the client upgrades to support the new version. However, the upgrade is not as clean as it might be, because they still have the saved locations pointing to the old version. The client either needs to support both versions, or write a tool that does, so it can migrate the url to their new locations. They could munge the urls, but if one of the incompatible changes was going from integer ids to UUIDs, they have no choice.

Luckily, HTTP has a built-in solution to this problem: Content Negotiation. It makes use of two headers, Accept on the client side, and Content-Type on the server side. The Tracker services serve everything back with a Content-Type of application/xml. Its not just any old XML, however, it is a specific form of XML, the schema of which is described in their API docs. This is the situation for which the use of mimetypes is intended. If every form of image out there just used a mime-type of image, we’d have a much harder time of things. Luckily, there’s more than that, with image/gif, image/png, and image/jpeg, which all represent different encodings of images. Following the same idea, Tracker could instead use something like application/vnd.pivotal.tracker.v1+xml. Yes, its still XML, but its Pivotal Tracker Version 1 flavor of XML. Then when Pivotal decides its time for incompatible changes, they only have to add an additional content type, application/vnd.pivotal.tracker.v2+xml.

Following this idea, now a project always lives at /projects/1234. This is better, because while v1 and v2 of a project probably aren’t different, their representations are. When a client updates versions, their links don’t break, nor do they have to support two or more versions.

I’ve only just brushed the surface of this topic. For more, Peter Williams has an excellent discussion of it here, here, and here. (disclaimer &emdash; Peter is a former coworker and personal friend. This section and his posts are about a solution we came up with for a project.)

Now You Don’t Have Any Excuses

I hope that this post serves as a good description of why you shouldn’t be designing web services the way every body else does. It seems that everyone is just copying everyone else, without really understanding the pros and cons of the implementations. I hope this sparks some discussion, because I don’t know that these are even the best way to be doing it, I just know from the experience of writing both applications and consumers, they way everyone is doing it now is much more difficult than it needs to be.

{ 30 } Comments

  1. Avdi Grimm | July 19, 2009 at 11:29 pm | Permalink

    Thank you, thank you, thank you for writing this. Some of the services calling themselves “RESTful” make me want to throw things. Specifically, they make me want to get a hardbound copy of RFC2616 and throw itat their developers’ heads. I read 2616 a long time ago and I don’t understand why so few “web developers” can be bothered to do so.

  2. Mike | July 20, 2009 at 12:43 am | Permalink

    Seriously, who cares if an API doesn’t fully comply with your dogma? No API out there passes your “purity” test and people choose what works and what’s easy for developers. These kinds of BS ‘religious doctrine’ commandments are detrimental to progress.

  3. Toby | July 20, 2009 at 3:00 am | Permalink

    All very good except this bit:

    ” Just about every HTTP server and proxy are able to handle caching, and if they operate to spec, they’re not allowed to cache SSL documents.”

    This is not even slightly true. There is nothing in any specification to suggest that caching behaviour should change according to whether SSL is used at the transport layer.

    Which means that in fact, you should use SSL as much as possible, to avoid MITM/credential sniffing attacks.

  4. August Lilleaas | July 20, 2009 at 5:05 am | Permalink

    Woha! That was certainly a wake-up call. The best part is that all of these four steps makes your API more awesome, not more pedantic. Thanks!

  5. Matt | July 20, 2009 at 6:35 am | Permalink

    Paul, this is great, thanks for posting. I do have a question however regarding your idea of mutable/changing/dynamic resource URLs.

    You mention ‘bookmarks’: “From a more practical standpoint, say a client is written when only version one of a service is available, and it stores (”bookmarks”) some of these resources…”

    However, some other information you present appears to be impractical in the presence of bookmarks:

    “By publishing a dozen or more well-known resources in their API docs, Tracker is no longer permitted to change any of them. This increases the maintenance burden, because now they have to maintain all these resources for the lifetime of the application, or deprecate any third-party clients.”

    Isn’t this true anyway, if we assume that resources will be bookmarked?

    “”If clients were to instead follow the href, they can do whatever they want to the id, and existing clients will have no trouble at all following.”"

    Again, this appears to be a false statement if we assume bookmarks.

    It seems to me, that once any resource URL is published, then that URL should be immutable and never change… either that or we should discourage bookmarking.

    Can you help clarify this issue?

  6. Michael S. | July 20, 2009 at 6:44 am | Permalink

    How should a RESTful service handle search? e.g. list of products matching “xxx”, top selling products, most frequently viewed. What verb should be used?

  7. Jonathan Freedman | July 20, 2009 at 7:12 am | Permalink

    Great read. Makes me think of the “let’s return a 500 server error with status 200″ crowd.

  8. Ilia Jerebtsov | July 20, 2009 at 7:43 am | Permalink

    You have to consider the implementation. In your methodology, if I want to access a resource of which I already have an ID (a common need), I need to go through your AllProjects resource to find it. That means that your server has to load up a huge list of projects, just so I can retrieve one. That’s fine if you have a few projects, but it does not scale.

  9. Matthew | July 20, 2009 at 8:25 am | Permalink

    Another part of REST which people often get wrong (in a well-intentioned way) is the use of PUT for partial update operations.

    In fact, PUT is specified for ‘complete replacement’, not ‘partial update’. It’s supposed to replace what’s current at that URI with the entire request body of the PUT.

    If you want to do partial update restfully, there’s a few options:

    Put to a subresource URL, eg /user/123/email_address POST to a special update URL, eg /user/123/update

    (Note these both require some kind of structured link or link template to the subresource / update URLs from the main resource)

    Use the PATCH method: http://tools.ietf.org/html/draft-dusseault-http-patch-13 which (IIRC) fielding says can virtually be treated as part of the HTTP spec. Note you can tunnel PATCH over POST if needs be in the same way people are tunnelling PUT and DELETE over POST.

    Note that ‘PUT to subresource’ does have an advantage over POST and PATCH in that the use of PUT guarantees it to be idempotent to any middleware.

  10. John Boxall | July 20, 2009 at 9:34 am | Permalink

    Following REST to the letter restricts client applications. How do you make a HEAD/PUT request in Flash? How do you change the accept HTTP headers?

    You might find Jacob Kaplan-Moss’ REST Worst Practices relevant: http://jacobian.org/writing/rest-worst-practices/

  11. Paul Sadauskas | July 20, 2009 at 11:25 am | Permalink

    @mike: It’s not dogma, I tried to list very practical and pragmatic reasons for doing it this way, the primary concern of which is to make things easier on developers, both future maintainers, and client writers.

  12. Paul Sadauskas | July 20, 2009 at 11:27 am | Permalink

    @Toby: No, an intermediate proxy cannot cache a document encrypted with SSL. Since everything (headers, body, uri) is all encrypted, how does it know what to cache?

  13. Paul Sadauskas | July 20, 2009 at 11:29 am | Permalink

    @Michael S.: By using a GET, with different resources. I would suggest, for each of your examples:

    /products?q=xxx
    /products/top_selling
    /products/frequently_viewed
    

  14. Paul Sadauskas | July 20, 2009 at 11:35 am | Permalink

    @Matt: If you do decide to move some of the existing resources, I would expect that you would also make use of the 301 Moved Permanetly response for the ones that moved. That way, a client can automatically update their bookmarks. A resource is not immutable, as long as the change is not one that breaks the API.

  15. foo | July 20, 2009 at 11:38 am | Permalink

    Using full urls for ids becomes impractical when you need to lay REST on top of existing db.

    If i have a record A that links to record B by some kind of id. I can have http://api/B/ in my record A. But if I want my users to be able to update record I have to validate, resolve and then destructure the url to extract the id.

  16. Paul Sadauskas | July 20, 2009 at 11:38 am | Permalink

    @Ilia Jerebtsov: It’s perfectly scalable. If the list really does get huge, there are plenty of methods available to mitigate the performance loss: pagination, caching, pre-build the document, or provide a search mechanism. I counter that providing an ID and asking the client to construct a url is not scalable, because then you cannot reorganize your resources, or move them across servers, or ever change the url scheme.

  17. Paul Sadauskas | July 20, 2009 at 11:40 am | Permalink

    @John Boxall: I don’t use flash, so I wouldn’t know. If it doesn’t allow you to use all the verbs in the http spec, or manipulate headers, I doubt that I ever will. It seems like a pretty huge deficiency.

    Also, I don’t see what that has to do with any of the points I made.

  18. Paul Sadauskas | July 20, 2009 at 11:43 am | Permalink

    @foo: That method is correct, but its hardly impractical. You must have code that already does that, because your application already extracted an ID of “A” from /api/A to be able to find the resource in the database. There’s no reason why you couldn’t use the same code path to extract “B” from /api/B. Far from being impractical, its trivial.

  19. Joe Fiorini | July 20, 2009 at 12:23 pm | Permalink

    @Paul First off, thanks for this post. I learned RESTful Services from the Sam Ruby book and even gave a few talks on it. Conversations (somewhat heated ones) with an attendee showed me that my understanding was wrong. Thanks to your post I now understand how to do it right. Word.

    Second, a question on your response to @Ilia: if I have the id of a resource, I theoretically could have a resource off / called “products”. I would access the “products” resource and give it a filter parameter of “id” to get that one resource, correct? Would that be an example of what you meant by “provide a search mechanism”?

  20. Paul Sadauskas | July 20, 2009 at 12:39 pm | Permalink

    @Joe Fiorini: Thanks for your kind words. Yes, REST is a rather orthagonal concept to what we’re used to. It took me quite awhile to get it figured out as well, and I’m still learning.

    As for your question, I would never expose an ID anywhere. To me, the way of uniquely identifying a resource is its “Universal Resource Identifier”. If you are looking for a particlular resource, I would use the same criteria to find it as you do to know which one you’re looking for, ie, “projects with a name of ‘My Project’”. Perhaps the resource would be /projects?filter=name:My%20Project.

    But thats only in the case when you have an extreme number of projects. More likely, you only have a few belonging to a single user or account, so its feasible to get the entire list and grep it for the criteria you’re looking for, without ever having to implement the search/filtering API.

  21. Coda Hale | July 20, 2009 at 3:14 pm | Permalink

    @Jonathan Freedman: Funny story—Apache and mod_proxy don’t play well with ErrorDocument, returning in error documents served as 200s. There’s a open bug for it.

  22. John Boxall | July 20, 2009 at 6:11 pm | Permalink

    @Paul - By providing versioning through content negotiation you limit what tools people can use to build against your API.

    “I don’t use flash, so I wouldn’t know. If it doesn’t allow you to use all the verbs in the http spec, or manipulate headers, I doubt that I ever will. It seems like a pretty huge deficiency.”

    Certainly it is, but it’s reality.

    Just as it is unacceptable for large sites to ditch IE support, it’s unacceptable for large APIs to ditch support for limited client libraries.

  23. Kent Brewster | July 21, 2009 at 7:57 am | Permalink

    Hi, Paul. This is a great jumping-off point for discussion, and I’m glad to hear we’re getting it mostly right at Netflix. :)

    I’d be interested to hear your take–and the opinions of the folks commenting here, who seem to be a smart, thoughtful bunch–on least odious compromises for API providers who must support Flash, OAuth, JSON-P, and other services and protocols that don’t have access to HTTP headers or verbs beyond GET and POST.

  24. bex | July 21, 2009 at 9:26 am | Permalink

    First you say:

    “there should be only one resource that is the starting point for any interaction with the service. This is called a ‘well-known’ resource, and is never, ever allowed to change locations”

    Then you say that you should never have version numbers in your URI. Stuff like this is forbidden:

    /v1/project/1234 /v2/project/1234

    That pretty much means that you will be permanently stuck with whatever information architecture you start out with. If you don’t organize your data 100% correctly the first time — which nobody does — you’re kind of screwed.

    Having a version number in the URI makes tons of sense to me…

  25. Dan Yoder | July 21, 2009 at 2:20 pm | Permalink

    I think this is great stuff. I’d like to point out that I’ve been trying to talk to some of the same issues on my blog. We need to get better at REST: there is so much potential here being wasted because we’re stuck on the browser.

    @John/@Kent - One solution is proxies that repackage the requests when a “dumb” User Agent shows up. One can also offer these clients a more limited API (because it will be intrinsically more brittle and thus more expensive to support) to encourage them to use another client. Hopefully, this, in turn, encourages vendors to improve their support for HTTP, proper.

  26. William Pietri | July 22, 2009 at 3:38 pm | Permalink

    Great article.

    Regarding Flash: Yes, it currently has poor support for RESTful APIs. That will never change if we build all APIs to coddle the world’s least-capable library.

    As a bridge, I recommend something like the Restlet TunnelService:

    http://www.restlet.org/documentation/2.0/api/org/restlet/service/TunnelService.html

    This lets you isolate the nonsense on the server side, and a similar bit of abstraction lets you limit the client-side mess. With the exception of those shims, the rest of your code on both sides can be properly RESTful.

  27. Rob Heittman | July 25, 2009 at 8:36 am | Permalink

    Good article. I also agree with August — following this guidance produces a better API. It’s not just pedantry.

    Still, there may be occasional valid reasons to diverge, usually in especially complex cases: Amazon certainly thought out their S3 authentication scheme carefully, though it is outside this guidance.

    I’m not convinced about versioned APIs. I fully agree this practice should be minimized, and I’ve seen it abused. But I also know of lots of cases where the API significantly and incompatibly differs and there is a user base reliant on a previous version. I am imagining a developer with a widely used REST API reads this blog post and goes back and rethinks their design (e.g. minimizing the starting points) — content negotiation alone might not cover the differences.

    So if a developer is not sure their REST API is correct, final, or long-term supportable, proactively introducing a version number is probably a good defensive practice giving you more flexibility to get it right in the future. IIRC Richardson and Ruby had stuff to say about this in their O’Reilly book, which has led many developers to REST, and may account for the prevalance of this practice.

  28. Ernesto | August 5, 2009 at 2:48 pm | Permalink

    Hi Paul,

    I like your article and I understand your point of view and the need for “getting it right”. But I still have a couple to doubts, some even related to past comments in this entry.

    First issue…

    For instance, Michael S. asks in comment #6 above about searching to avoid clients to retrieve (GET) all resources of a given kind to then find/navigate to a specific one.

    You then answered in comment #13 with “suggestions”. But since clients ignore any specifics about the API of a system, and need only to know a single entry point with hyperlinks to the available services, how are clients suppose to “discover” or learn how to search? I mean, they might learn that product resources can be find at “/products”, but if they want to filter or search within all products, how do they know what querystring parameter to use, or any other implementation specification to search this resources?

    And the second issue, which is not a doubt but a rant. Ruby on Rails, which on one hand has contributed a lot by “spreading the word” of restul interfaces (I first knew about REST from rails) but today with your article and roy fielding’s original dissertation about it, I have learned that rails, far from helping, has spread the wrong idea about what a RESTful interface is, because rails is not [fully] compliant.

    Rails relies on a predetermined URI structure, but when a design implementation changes this structure, all clients get broken. ActiveResource, for instance, relies heavily on this. And I have learned today all this and I feel so bad. It’s preferable not to adopt it at all, than to wrongly adopt it.

  29. ABRAR | December 26, 2009 at 5:39 am | Permalink

    AMAING VIDEOS >>>WWW.4URTUBE.BLOGSPOT.COM

    200++ TV CHANNELS http://WWW.4URTV.BLOGSPOT.COM

    SEND FREE SMS IN PAKISTAN ANY NETWORK UNLEMITED & SEND FREE SMS IN WORLD http://WWW.4URFREESMS.BLOGSPOT.COM

    FREE CHAT ROOM IN PAKISTAN & AND ALL WORLD http://WWW.4URCHATROOM.BLOGSPOT.COM

    http://WWW.PAKDESK.TK

  30. Hedgehog | February 6, 2010 at 8:41 pm | Permalink

    Doesn’t Roy explicitly contradict your second point, “‘Don’t Make a Client Construct URIs” ?

    Specifically: “Instead, allow servers to instruct clients on how to construct appropriate URIs, such as is done in HTML forms and URI templates, by defining those instructions within media types and link relations.”

{ 11 } Trackbacks

  1. To REST or not to REST | July 20, 2009 at 2:42 am | Permalink

    [...] Sadauskas, on another article about the same subject, adds some rules that your API should not [...]

  2. [...] The Amazing Blog : Your Web Service Might Not Be RESTful If…theamazingrando.com [...]

  3. popurls.com // popular today | July 20, 2009 at 3:20 am | Permalink

    [...] Clogged Toilet At Space Station Lifehacker, tips and downloads for getting things donedeliciousThe Amazing Blog : Your Web Service Might Not Be RESTful IfSEOmoz | 10 Steps to Advanced Keyword Researchxkcd - A Webcomic - Estimation22 Very Useful Adobe [...]

  4. [...] Illustrator Tutorials Web Design Ledger 50+ Fresh and Unique Personal Portfolio Websites Noupe The Amazing Blog : Your Web Service Might Not Be RESTful If 15 Plugins to Unleash the Invincible Power of jQuery and WordPress QuickFlip 2: The jQuery Flipping [...]

  5. Is this RESTful? at subbu.org | July 20, 2009 at 3:55 pm | Permalink

    [...] have been holding off this post for over a month. But having seen the latest post titled Your Web Service Might Not Be RESTful If… by Paul Sadauskas, I am motivated to publish this (not that his post is dogmatic – it is [...]

  6. [...] The Amazing Blog : Your Web Service Might Not Be RESTful If… [...]

  7. [...] Your Web Service Might Not Be RESTful If… [...]

  8. [...] Your Web Service Might Not Be RESTful If… [...]

  9. [...] perhaps more digestible and to the point than this paper is a blog post recently published by Paul Sandauskas in his blog, where he warns developer about not being fully [...]

  10. » links for 2009-08-15 (Dhananjay Nene) | August 15, 2009 at 2:01 pm | Permalink

    [...] The Amazing Blog : Your Web Service Might Not Be RESTful If… (tags: rest) [...]

  11. [...] Your Web Service Might Not Be RESTful If you have a API/Key/Token in a header/URL, have a version st…; [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *