i concur On Mon, Dec 27, 2010 at 6:00 AM, <dancer-users-request@perldancer.org>wrote:
Send Dancer-users mailing list submissions to dancer-users@perldancer.org
To subscribe or unsubscribe via the World Wide Web, visit http://www.backup-manager.org/cgi-bin/listinfo/dancer-users or, via email, send a message with subject or body 'help' to dancer-users-request@perldancer.org
You can reach the person managing the list at dancer-users-owner@perldancer.org
When replying, please edit your Subject line so it is more specific than "Re: Contents of Dancer-users digest..."
Today's Topics:
1. Re: Dancer::Plugin::REST proposal (Puneet Kishor)
----------------------------------------------------------------------
Message: 1 Date: Sun, 26 Dec 2010 07:43:48 -0600 From: Puneet Kishor <punk.kish@gmail.com> Subject: Re: [Dancer-users] Dancer::Plugin::REST proposal To: Naveed Massjouni <naveedm9@gmail.com> Cc: dancer-users <dancer-users@perldancer.org> Message-ID: <4D174694.6050307@gmail.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed
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:
DISCLAIMER: 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
vs.
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 http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
<quote> - 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. </quote>
That last item, "Extending a database through an append operation," corresponds to my scenario.
Further down in the same RFC
<quote> 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. </quote>
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@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 ===========================================================================
------------------------------
_______________________________________________ Dancer-users mailing list Dancer-users@perldancer.org http://www.backup-manager.org/cgi-bin/listinfo/dancer-users
End of Dancer-users Digest, Vol 10, Issue 45 ********************************************