[Dancer-users] Dancer::Plugin::REST proposal

Puneet Kishor punk.kish at gmail.com
Sun Dec 26 14:43:48 CET 2010

First, my thanks to Alexis for writing Dancer::Plugin::REST (DPR), and 
thanks to Naveed for continually responding to my persistent questions 
and now continuing this very important thread. Supporting REST (via DPR) 
should be a core objective of Dancer, by making it as easy as pie 
(although, personally, I have never found making a pie to be easy -- the 
crust in particular requires great skill). REST is the core of linked 
data and the semantic web, and these are great technologies and 
objectives worthy of support.

More below.

Naveed Massjouni wrote:
> I know this is the mailing list for Dancer, but I am writing about a
> particular plugin.  I think it is relevant because it is a pretty
> important plugin and also because I would like to hear everyone's
> opinion.  Especially Sukria, since it's his plugin.
> There has been several REST related posts recently and it has reminded
> me of something that has been bugging me about the
> Dancer::Plugin::REST module.  It provides the keyword resource which
> works as follows:
>      resource user =>
>          get    =>  sub { # return user where id = params->{id}   },
>          create =>  sub { # create a new user with params->{user} },
>          delete =>  sub { # delete user where id = params->{id}   },
>          update =>  sub { # update user with params->{user}       };
> But a PUT/POST in REST does not always correspond to UPDATE/CREATE.

 From what I understand, PUT and POST may be interchangeable, but here 
is how it should play out. PUT should be used when the resource name is 
known in advance. POST should be used when the resource name is not 
known in advance. So, the following scenario --

PUT http://server/Puneet-Kishor


POST http://server/{a bunch of data that would create a new resource 
whose URI would be 'Puneet-Kishor'}

The above seems silly because in the latter scenario (the POST) too I 
know what the name of the resource is going to be. But, such is not 
always the case. For example, in my current scenario, I am allowing 
users to do some analysis and then save that analysis with an easy to 
remember name. However, there is no guarantee they will always choose a 
unique or a meaningful name. The name is just a mnemonic for making it 
easy for *a* user to remember what she did, not a guarantee for global 
uniqueness (GFGU). The GFGU is promised via an analysis ID created by 
the primary key of the data store in which the analyses are stored.

Additionally, in my scenario the retrieval of the resource is via the 
idea such as

GET http://server/17

which gels well with the idea of sending a bunch of data to the server 
via a POST, and letting the server generate the ID that will become the 
URI for that resource.

Of course, in the above scenario, POST also corresponds to an update.

See the definition of POST from 

       - Annotation of existing resources;
       - Posting a message to a bulletin board, newsgroup, mailing list,
         or similar group of articles;
       - Providing a block of data, such as the result of submitting a
         form, to a data-handling process;
       - Extending a database through an append operation.

That last item, "Extending a database through an append operation," 
corresponds to my scenario.

Further down in the same RFC

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.

And, finally, "The methods GET, HEAD, PUT and DELETE" should be 
idempotent. This means that repeated applications of these methods 
should result in exactly the same effect on the store as a single 
application. Obviously, POST doesn't belong in this list because 
repeated applications of POST (an update) does modify the store 
differently each time.

I believe Dancer should follow RFC 2616 Section 9 to the t in order to 
be a good semantic web citizen.

> One of my favorite articles on this topic is:
> http://jcalcote.wordpress.com/2008/10/16/put-or-post-the-rest-of-the-story/
> It's worth reading even if you don't agree with it in the end.  It
> will at least show you a different perspective.  Also, his argument is
> backed up by the HTTP spec.  He argues that a PUT can be used to
> update or create a resource, and the same for a POST.
> So I have some proposals that could make everyone happy, hopefully.
> Even if you are happy with the existing CRUD mapping.  I think the
> REST plugin should also support mappings from a resource to http
> verbs, in addition to the way it works now.  For example:
>      resource user =>
>          get    =>  sub { # return user where id = params->{id}   },
>          create =>  sub { # create a new user with params->{user} },
>          delete =>  sub { # delete user where id = params->{id}   },
>          update =>  sub { # update user with params->{user}       },
>          # and also
>          post   =>  sub { },
>          put    =>  sub { };
> Even better is if it supported a dispatch table style:
>      resource user =>  {
>          get    =>  sub { },
>          delete =>  sub { },
>          post   =>  sub { },
>          put    =>  sub { },
>      };
> Notice that the second argument to 'resource' is a hashref in the
> above example.  Another cool thing it could support is:
>      resource user =>  'User';
> Where 'User' is a package/class that could be defined in User.pm:
>      package User;
>      sub get { ... }
>      sub delete { ... }
>      sub post { ... }
>      sub put { ... }
>      1;
> Another thing that could be improved is that the 'resource' function
> throws an exception if the user did not provide mappings for all 4
> operations/verbs.  But there is no requirement that a resource should
> support all http verbs.  The 'resource' function could provide routes
> which return a status of 405 Method Not Allowed, for the missing
> verbs.
> Do you guys like any of these ideas?  Should these ideas be
> incorporated into the existing REST plugin or a new plugin?  I would
> be glad to implement them, but I wanted to make sure my changes would
> be accepted before doing the work.

I like your ideas very much. I like the mapping of "resource" to a 
package that in turn implements the methods, and that throws an 
exception of all 4 verbs are not supported, but also allows a manual 
override. Mapping to a package will allow me to cleanly build interfaces 
for my different kinds of data, allowing me to separate the treatment 
for each kind of data in its own package.

However, most important, by following RFC 2616-9, your proposed 
direction would make my application really useful, predictable, and in 
conformance with the expectations of the world of linked data.

Dancer is truly a wonderful framework. In the beginning its new and easy 
style for building a web application excited me. Now I am realizing a 
new purpose for Dancer. Even though I am putting a lot of work in my web 
application, suddenly I care less about that application than in the 
access to the data. Suddenly the user of the application is less 
important than the user of the data. In fact, my application itself has 
become an user of my data.

Thought carefully through, Dancer can really make very important 
contributions to the world of semantic web and linked data by allowing 
Perl practitioners build useful data access applications that follow the 
recommended, modern principles.

> Regards,
> Naveed
> _______________________________________________
> Dancer-users mailing list
> Dancer-users at perldancer.org
> http://www.backup-manager.org/cgi-bin/listinfo/dancer-users

Puneet Kishor http://punkish.org
Carbon Model http://carbonmodel.org
Charter Member, Open Source Geospatial Foundation http://www.osgeo.org
Science Fellow http://creativecommons.org/about/people/fellows#puneetkishor
Nelson Institute, UW-Madison http://www.nelson.wisc.edu
Assertions are politics; backing up assertions with evidence is science

More information about the Dancer-users mailing list