Ian Bicking: the old part of his blog

HTTP verb distaste

I was looking this unassuming post from a while back, and thinking about callbacks from this comment, and I started getting that annoyed feeling about REST and HTTP verbs, but I wasn't sure why. Now I think I know why: the way HTTP verbs are being suggested they are a poor substitute for callbacks, and callbacks are easily attainable right now if we just pay attention to them.

To summarize the verb argument (as I understand it): using different verbs on the same resource allows you to make a cohesive set of actions that work on a well-defined entity, and the entity is represented by the resource URL. Because the HTTP verb is orthogonal to the resource URL, you keep object and verb very separate.

What do the verbs mean? This is communicated via some other channel, probably documentation. It is not always self-evident. DELETE means delete? Only if you have a dumb container. If you don't have a dumb container, DELETE probably means more than just delete -- it has side effects outside of the resource in isolation.

I was reminded of this again with Mark Nottingham's post about links, which is this idea of callbacks again, about defining explicit relationships instead of implying. He extends it with link templates, like http://www.example.com/home/{userid}, which can represent some more complex relationships. One of the nice parts about something like this is that http://www.example.com/userhome.php?userid={userid} works just as well in this scheme. That is, it works for the systems we have now, not just the systems we want to create in the future.

The problem with depending on "RESTful" URLs, verbs, and other contracts is that it isn't the web we have now. And it's definitely not a simpler web, because the web we have now isn't going away. There are complaints such that userhome.php?userid={userid} isn't likely to be a stable URL. Well, creating a new URL scheme for the site certainly isn't the way to solve that!

Good designs have to deal with what we have, not just with what we wish we had. You have to embrace the problems, recognizing them as part of the success. The W3C's pursuit of XHTML over enhancing HTML is one such example, and we've all spent a whole lot of time accomplishing nothing as a result. Much of REST is great because it embraces what we already have, because it describes the systems that already work well. But some of what goes under the REST flag does not fit this. The systems we have now do GET and POST really well; everything else is spotty. If we need more than GET and POST, then that has to be resolved. But I don't see why we would need more; those two verbs describe just about everything we need, and they do it with a proper amount of vagueness, not describing much more than what they can deliver.

Something like Link Template headers (or even more conservatively <link>) provide a much greater vocabulary, and they are so wonderfully composeable compared to HTTP verbs. I think that's a much more interesting direction.

Created 23 Jun '06

Comments:

Ian,

Could you please define "the web we have now"? I fail to understand your point as I am not certain of what you mean by this assertion.

Thanks

# Sylvain Hellegouarch

I mean web applications people have been building in the field, implemented for the current batch of browsers.

# Ian Bicking

Well then I'm sorry but I do not understand your point at all. REST is not effective today because it is still widely misunderstood IMO (I'm not saying I understand it cmprehensively). Too many people think RESTful URLs equal REST application. It is so wrong. RESTful URLs are a mean. REST is a set of principle.

I really miss your point here Ian.

# Sylvain Hellegouarch

I perhaps state my anti RESTful URLness too strongly. There's obviously nothing wrong with such URLs. There's just not much particularly right about them either. They are just strings either way. How they are read by humans isn't very important. The verbs are more important, and using more verbs presents real problems with existing applications and clients.

# Ian Bicking

I don't think you can really think about a purely RESTful approach when you're using a browser since usually you can only GET or POST from the browser.

The RESTful approach is quite powerful when applied to web services (REST+Atom, look at GData for a real use case) that are meant to be used by a machine and not a human.

Other than that I personally think that:

http://www.example.com/user/{userid}

is quite more pleasant to work with than:

http://www.example.com/userhome.php?userid={userid}

for two main reasons:

  1. Easier to remember for humans
  2. Not bounded to implementation details of any sort

Regarding point n°2, the example you're providing is exposing two major implementation details:

this can provide useful information to someone who is trying to attack your site/application but even more important will force you (the developer) to keep the same scheme even if you're going to rewrite your app in another language.

Other than that I agree with Sylvain that your points regarding "the web we have now" are somewhat vague IMHO. ;-)

# michele

I'm gonna add something about http://www.example.com/user/{userid}

I'm changing servers as well as backend languages as we speak. It's a lot easier if the url is not bound to a particular programming language.

example:

http://www.example.com/userhome.asp?userid={userid}

becomes

http://www.example.com/userhome.jsp?userid={userid}

becomes

http://www.example.com/userhome.php?userid={userid}

becomes

http://www.example.com/userhome.aspx?userid={userid}

becomes

http://www.example.com/userhome.py?userid={userid}

and eventually:

http://www.example.com/user/{userid}

# Christopher Mahan

But

http://www.example.com/userhome?userid={userid}

is easily rewritten by Apache to fit any of those others. I think you're conflating two separate issues.

# Randall Randall

That's exactly right. One additional note on the following two URLs:

http://www.example.com/user/{userid}
http://www.example.com/userhome?userid={userid}

I'm not sure why the examples given so far have used two different forms of the URL (i.e. /user/... and /userhome...). To really compare apples to oranges I will use these:

http://www.example.com/user/{userid}
http://www.example.com/user?userid={userid}

These two URLs exhibit the difference between positional and keyword arguments in Python. The python equivalent would be:

from www.example.com import user
user(1)
user(userid=1)

Given that distinction, they really are not the same at all (although both forms may work in Python if the first parameter of the user() function happens to be named "userid"). While some may argue that the first form is more "REST-ful", I would say simply that they are not the same and cannot be compared that way. The first form derives the meaning of the parameter from its position within the URL. In contrast, the second derives the meaning of the parameter from its explicit name.

There is one gotcha here though: conventionally "keyword arguments" are ignored by web servers if they are not "needed" by the server/script. This has the implication of making a set of textually unique URLs resolve to a single resource. For example:

http://www.example.com/user?userid=1
http://www.example.com/user?userid=1&count=10

Depending on the implementation of the "user" page/script, these two URLs may or may not refer to the same resource. This may be viewed as either a benefit or a disadvantage in the implementation of HTTP servers. Of course the same thing could happen with "positional" arguments in HTTP. Given a sufficiently flexible (or ill-configured) server, the following two URLs may refer to the same resource as well (although it would violate convention):

http://www.example.com/user/1
http://www.example.com/user/1/10

I would argue that the thing that needs to change is the ability of web servers to easily map arbitrary URLs to arbitrary resources. The structure of directories and files on a server is an outdated and constrained model. Even more outdated and outrageous is the use of file extensions to determine resource types. ModRewrite is a poor solution because it is far too complicated to configure for novice users. It's like trying to use a jackhammer to pound a finish nail--its nearly impossible to determine what it will hit unless you're well exercised in the art of regular expressions and other various criptic configuration giberish.

# Daniel

I always seem to find interesting blog posts by you long after you wrote them ;)

Some time I'm going to take another shot at nailing this whole MVC "vs." REST thing (which is to me far more interesting than REST vs. SOAP) - tried and failed once already here: http://www.sitepoint.com/blogs/2005/12/22/mvc-and-web-apps-oil-and-water/

What I was grasping for in "Who GETs REST?" (http://www.sitepoint.com/blogs/2005/11/22/who-gets-rest/) is a single rule / guideline people could use, from which a whole bunch of other consequences naturally fall out, without having to be able to grasp the whole of REST. But think that failed.

The real point is I think that 99% of today's web frameworks put you through loops as a developer are either just horrible or dangerous. By contrast, if we had an API which relates directly the REST, my guess is the whole web dev thing gets alot easier for real people to grasp - it would be natural even if you don't know much about HTTP.

Looking at what we've got today...

Considering struts - it's amazing that people are willing to accept that kind of API. The concepts struts pushes you to think in terms of (Actions, ActionMappers blah blah) have _zero_ relationship to the medium - HTTP. Struts becomes some kind of Zen excercise of thinking in 13 dimensions. There's only an artificial correspondance between URLs and code you're writing. And somehow the idea that a framework constrains how you use URLs is deeply wrong.

Meanwhile the Rails / Catalyst / Django / Turbogears approach - URLs to class methods has inverted the problem - it's almost too easy. Relateing URLs to class methods means people are "tunneling" all kinds of verbs through HTTP GET (delete/list/index/show/find/findByName etc. etc.) - and from there we have the whole "Goodnight Moon" factor (Mark Pilgrim, as a new father, being very dry - http://www.intertwingly.net/blog/2005/05/06/This-Stuff-Matters#c1115432785)

Perhaps the acid test is "how easy is it to implement conditional HTTP GET's"? This point doesn't travel so well, which is a shame - it's another "rule to illustrate the point" rather than a mere feature request. In both the above two MVC framework styles, doing any kind of HTTP caching is code you're going to have to tack on as a (very) painful after-thought.

To me the obvious "right path" is mapping URLs / resources to classes, which have methods corresponding to HTTP methods - then you get to have a property "last_modified" and your framework can handle the HTTP caching for you automatically.

Of the REST frameworks out there, web.py has the API right but is still being too light weight to provide "off the shelf" resources, which would help. There's also tonic (PHP) http://tonic.sourceforge.net/ which seems to be getting some of the fundamental ideas right, but needs to be more than a one-developer code base. Then there's RESTLET (http://www.restlet.org/) which looks promising but, in usual Java style, it's embraced choice (e.g. server container support) as a path to wasting my time. Also Rails finally seems to be heading this way (http://jimonwebgames.com/articles/2006/06/26/dont-say-crud-say-fucd) without complete submission though on the new method names. But no one seems to be _really_ there yet.

And in fact it's not really MVC vs. REST. The value of MVC-style seperation or concerns goes without saying but the problem is people tend to consider MVC as open season to inventing a ton of verbs for their application, but with HTTP the verbs are already fixed (and emphasize coarse grained APIs) - the nouns are where you get to have a choice - not a natural consequence of MVC.

At a fundamental level, the whole thing is kind of bizarre - it's taken this long for people to figure out how to write code to such a simple and widely used protocol (even if it is only half-implemented). It's like on the one hand we've got the "who gives a sh*t" crowd, hacking away with stuff like PHP, oblivious until someone tells them something else is cool while on the other we've got the "I love complexity" crowd, happy to buy obscure (typically Java) abstractions to flagellate themselves with, never questioning whether it's a good idea or not.

Anyway.

# Harry Fuecks