How to implement RESTful requests? A proposal

38 views
Skip to first unread message

billf

unread,
Oct 23, 2008, 8:26:12 AM10/23/08
to web2py Web Framework
I have put together a page that proposes an approach to handling
requests in a RESTful manner - well it looks RESTful to me.

As Steve Shepherd has said, the benefit of a group like this is the
ability to comment and provide feedback, so please see the example as
a starting point and feel free to criticise.

As the example is longish I have put it on a separate page at
http://www.wellbehavedsystems.co.uk/web2py/examples/rest.html

Timothy Farrell

unread,
Oct 23, 2008, 8:52:24 AM10/23/08
to web...@googlegroups.com
I like this a lot. If Massimo agrees this could be the "official
recommendation" for CRUD operations via a RESTful URL interface. Such
concepts would have been helpful for me whenever I started into web
development since it would show me how to look at data manipulation.

Thanks for your effort on this.

-tim

tfarrell.vcf

mdipierro

unread,
Oct 23, 2008, 10:01:14 AM10/23/08
to web2py Web Framework
Thank you Bill,
Give me some time to digest this. This is a busy week.
I would also like to hear more opinions in this regard.

Massimo
> tfarrell.vcf
> < 1KViewDownload

voltron

unread,
Oct 23, 2008, 12:40:48 PM10/23/08
to web2py Web Framework
I am not sure if your proposal would work with RESTful clients
because you are not using the HTTP protocol to differentiate the
actions taken.

What about using decorators?

http://pylonshq.com/docs/0.9/module-pylons.decorators.rest.html

Or a workaround as Massimo suggested once

http://groups.google.com/group/web2py/browse_thread/thread/8506105246e319f6/7b7fa673ffbdab37?hl=en&lnk=gst&q=rest#7b7fa673ffbdab37

billf

unread,
Oct 23, 2008, 1:07:13 PM10/23/08
to web2py Web Framework
Voltron

As I say, REST is new to me, but I believe the practical problem is
the lack of true REST clients. Most of us have to make do with HTML
forms from clients that only support GET and POST. If someone wants
to develop a real-world app using REST "style" URIs then I think
something like I propose would be necessary.

To cater for true REST clients, it would seem easy enough (from your
links) to handle both. For example, (pseudo-code) if (http-
method==DELETE) or (http-method==POST and request.arg[-1]==delete) do
delete().

Whether checks are performed as decorators or inline ifs seems beside
the point.

On Oct 23, 5:40 pm, voltron <nhy...@googlemail.com> wrote:
> I am not sure if  your proposal would work with RESTful clients
> because you are not using the HTTP protocol to differentiate the
> actions taken.
>
> What about using decorators?
>
> http://pylonshq.com/docs/0.9/module-pylons.decorators.rest.html
>
> Or a workaround as Massimo suggested once
>
> http://groups.google.com/group/web2py/browse_thread/thread/8506105246...

billf

unread,
Oct 23, 2008, 8:40:38 PM10/23/08
to web2py Web Framework
Voltron

I have read through the threads you referenced again and I think I can
see where you are coming from.

I think that part of the problem is that examples of REST rarely seem
to include the parts of the user interaction where the user requests
an HTML form to be used to create/update/delete. The examples seem to
assume knowledge at the client end that would enable a PUT, POST or
DELETE to be generated without any prior GET. I can see how this is
possible but this is not generally the case with HTML interactions,
hence the need to encode additional information in the GET to
differentiate between:
- return a list and return a create form
- return a read-only version and return an edit form (with an option
to delete?)

Taking the list vs create case, which of the following forms of GET
would you prefer to see (assuming .../default/locations returns a
list):
- ...default/locations/create
- ...default/locations?form=create
- ...default/createlocationform

It would be a shame if you selected the last one :-) as I think that
all the "locations" requests going through the same controller/action
has a certain elegance. Whichever you select, I assume that "search"
would be handled similarly.

Taking the read-only vs update/delete case, which of the following
forms of GET would you prefer to see (assuming .../default/locations/1
returns a read-only version, i.e. not a form):
- ...default/locations/1/update
- ...default/locations/1?form=update
- ...default/updatelocationform?id=1

As for the "POST" or send part of the interaction, you suggest
overloading POST via a CGI parameter (after the ?). This seems
equivalent to overloading via a URI element (?_rest_method=DELETE
versus /delete) but I think a parameter is better as it leaves a
cleaner URI. The only downside is a lack of symmetry between the GET
and POST for create and update but I don't think that is significant.
The revision would mean that the POST for create and update would look
like:
...default/lookups?_rest_method=PUT&etc

...and the action determined by the id parameter (present and non-zero
for an update, absent or non-zero for a create).

Depending upon your responses, I would be happy to write up an
alternative example to enable people to compare.

What do you think?

billf

unread,
Oct 24, 2008, 1:11:35 PM10/24/08
to web2py Web Framework
I have posted an alternative example based on the last couple of posts
which is, I think, an improvement. It can be found at:
http://www.wellbehavedsystems.co.uk/web2py/examples/rest_alt1.html

It is fully working (so far) with the exception of:
- it doesn't yet generate a read-only details page prior to a delete
(but the update form delete checkbox works)
- a cosmetic issue: lists are labelled 'resource' as opposed to the
table name

mdipierro

unread,
Oct 24, 2008, 2:00:09 PM10/24/08
to web2py Web Framework
What is authenticate()? Did you use a modified version of the plugin?

Massimo

billf

unread,
Oct 24, 2008, 2:17:01 PM10/24/08
to web2py Web Framework
Massimo

If you read the last comments before the code under "The
implementation", I detail 3 patches to T2 code:
* in T2.__init__, use the first numeric request.arg as the id as
opposed to request.arg[-1]):
* copy requires_login, rename as authenticate and modify to allow
calling inline
* enable next function to be a list by modifying update() to not
override "None" with "[id]"

If delete() is changed to output read-only details with a "Delete"
button that would a fourth patch.

mdipierro

unread,
Oct 24, 2008, 2:56:54 PM10/24/08
to web2py Web Framework
There was a reason for the [-1].

T3 (not t2) is a wysiwyg wiki that works on gae and allows you to
embed {{=t2....}} tags in the pages. The pages are then saved in the
datastore. In tis case there is a single action and args[0:-1] are
used to identify the page. args[-1:] are used by the embedded
components.

I am no saying this is the best way. Just explaining my reasoning.

Massimo

billf

unread,
Oct 24, 2008, 3:38:01 PM10/24/08
to web2py Web Framework
The patch is only necessary in the original example because the form,
when present, followed the id. The alternative REST approach does not
require that patch. Another reason in favour of the alternative
approach.

Steve Shepherd

unread,
Oct 24, 2008, 5:10:32 PM10/24/08
to web...@googlegroups.com
Bill

My only question with your rest example is how do we handle multiple potential actions.
For example what if the it is not just one create action taking place.
Does the coder have to code a meta action that then chains into the sub actions.
How would rest handle this?

Steve

billf

unread,
Oct 24, 2008, 11:45:14 PM10/24/08
to web2py Web Framework
Steve

Do you mean "when I create an A I want to do X, Y and Z?" I don't
think that is really about REST as such.

My first thought is: pass a callback function via onaccept= and do it
in that, e.g.

resource=Resource(db.widget,onaccept=createotherwidgetstuff)
Reply all
Reply to author
Forward
0 new messages