Difficulty PUTting up with REST

I want to be a good REST citizen. I really do. But it’s not easy.

GET is supposed to be idempotent and side-effect free. Excellent. I’m all for it.

So here I am putting together a little app and I need to design my Web API. The right thing to do is:

PUT http://parand.com/sessionid/currentState (change state)
GET http://parand.com/sessionid/currentState (get state)

Neat. One URL for both. (Btw, is the session ID in right place? Should it be http://parand.com/currentState/sessionid instead?)

Now to actually make it happen. The API will mostly be called from Web browers (AJAX!), and thankfully XMLHTTPRequest supports PUT. Good.

But how does the backend handle PUT?

Hmm. I’ve handled GET and POST plenty, but how does one do PUT? Apparently with something like this on CherryPy.

So I need to plug in this new piece of code as my main controller, which makes me nervous. But more than anything, I just don’t want to think about this. This is just plumbing for my silly little app, and I want to think about the app instead of how to handle PUT. I’m sure handling PUT is built into CherryPy, but I can’t seem to find it.

Btw, notice how CherryPy’s philosophy is that GET and POST should be transparent to the developer:

It doesn’t matter whether the parameters are sent with a POST or a GET, or if they’re a small string or a large file that’s being uploaded. They always end up being converted to a regular python string and they’re passed as an argument to the function. It’s all transparent to the developer!

Did I get that right? Isn’t that very not REST?

Now that I think about it, I’ll probably have visual basic clients also, and possibly plugins to various Office products. Do those do PUT? I know they do GET.

Anyway, I’m trying to persevere and keep on my little quest to do PUT. But the trouble is, these little guy keeps calling me:

http://services.parand.com/setCurrent/sessionID
http://services.parand.com/getCurrent/sessionID

Bad, bad. I try to ignore them, but there’s this little voice that keeps telling me I could’ve implemented my API already if I had just gone with GET from the beginning instead of all this digging around.

So I’m sure there’s an easy way to do PUT, but it’s eluding me, and I’m very tempted to just GET on with it. To all the RESTians out there, how about putting together guides that spell out exactly how to implement PUT (and all the rest of the REST recommendations) on all the different back-end (and front-end while we’re at it) technologies out there? Philosophy is good, but particality is driving.

3 Comments so far

  1. Mark Baker on December 27th, 2005

    “Did I get that right? Isn’t that very not REST?”

    Yup. This is a pretty common bug in many web app frameworks. CGI does it (unless you know to look for the method). Zope does it. Ruby on rails does (did) it. Others too…

    As for recommendations re PUT, see;

    http://www.intertwingly.net/wiki/pie/PutDeleteSupport
    http://www.intertwingly.net/wiki/pie/CarrotVsOrange

  2. Chris Radcliff on December 28th, 2005

    I’m right there with you. We went through the same process when deciding how to do the EVDB API (http://api.evdb.com/docs). We ended up going with a RESTful but not RESTafarian implementation, basically adding the verb to the URL instead of using HTTP actions as verbs, plus removing the object ID from the URL and shifting it to the query string. Thus:

    http://host/rest/noun(s)/verb?id=ID
    e.g. http://api.evdb.com/rest/users/locales/list?id=chris_radcliff

    I’m sure there was some ideologically pure way of constructing all of our methods using HTTP verbs, but we made the decision to do it this way in order to make it easier for us to develop, test, and explain. We’re still getting all the benefits of REST, as far as we can tell.

  3. [...] As to why this might not work, see what Parand had to say about it. [...]

Leave a Reply