[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:
> 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 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