a REST question immediately followed by a Dancer-implementation question
So, I have a lot of methods such as get '/foo' => { .. }; get '/bar' => { .. }; get '/baz' => { .. }; get '/qux' => { .. }; All the above methods are reachable via a browser in which they depict some visual representation of the data. Most of the above methods have their '.:format' counterparts, mostly returning JSON packets when reached either via the browser or via the command line. All the methods above return something by default or modified by parameters. So, "http://server/app/foo" may work, or may require some parameters as in "http://server/app/foo?age=27&before=yesterday&for=rascals" I would like to implement a "meta" method, say get '/rest' => { .. }; which should return a listing of all the methods above, along with their parameters, if any, and whether those parameters are optional or required. http://server/app/rest {"resources": [ {"name": "foo, "params": [ {"required": [ {"name": "age", "type": "int"} ]}, {"optional": [ {"name": "before", "type": "string"} {"name": "for", "type": "string"} ]}, ]} ]} In other words, this meta method returns all the resources available at the http://server/app. Of course, I could code this for each app, but it would be nice to automate it. Suggestions? Ideas? -- Puneet Kishor
A few additional thoughts -- I guess I am looking for a "metaprotocol" (just learned that word on reading about Moo, and wanted to use it) that returns all the routes in the app, combined with some kind of params-validate + error reporting mechanism. So, companion questions -- for you Dancers, what are the params-validate and croak/confess/carp modules of choice? I (and I believe most of you) tend to lean toward lean and light, something that doesn't profess to do everything in the world, but in return, is a few orders of magnitude lighter than the big-well-known-brand out there. On Sep 30, 2011, at 8:51 AM, Mr. Puneet Kishor wrote:
So, I have a lot of methods such as get '/foo' => { .. }; get '/bar' => { .. }; get '/baz' => { .. }; get '/qux' => { .. };
All the above methods are reachable via a browser in which they depict some visual representation of the data.
Most of the above methods have their '.:format' counterparts, mostly returning JSON packets when reached either via the browser or via the command line.
All the methods above return something by default or modified by parameters. So, "http://server/app/foo" may work, or may require some parameters as in "http://server/app/foo?age=27&before=yesterday&for=rascals"
I would like to implement a "meta" method, say
get '/rest' => { .. };
which should return a listing of all the methods above, along with their parameters, if any, and whether those parameters are optional or required.
http://server/app/rest {"resources": [ {"name": "foo, "params": [ {"required": [ {"name": "age", "type": "int"} ]}, {"optional": [ {"name": "before", "type": "string"} {"name": "for", "type": "string"} ]}, ]} ]}
In other words, this meta method returns all the resources available at the http://server/app.
Of course, I could code this for each app, but it would be nice to automate it.
Suggestions? Ideas?
-- Puneet Kishor
On Fri, Sep 30, 2011 at 9:51 AM, Mr. Puneet Kishor <punk.kish@gmail.com>wrote:
In other words, this meta method returns all the resources available at the http://server/app.
Of course, I could code this for each app, but it would be nice to automate it.
Suggestions? Ideas?
I would imagine you could use Dancer::Plugin::Sitemap as a starting point to do something to this effect. It looks through the routes and you could create your own plugin to do it.
On Sep 30, 2011, at 9:10 AM, Dave Doyle wrote:
On Fri, Sep 30, 2011 at 9:51 AM, Mr. Puneet Kishor <punk.kish@gmail.com>wrote:
In other words, this meta method returns all the resources available at the http://server/app.
Of course, I could code this for each app, but it would be nice to automate it.
Suggestions? Ideas?
I would imagine you could use Dancer::Plugin::Sitemap as a starting point to do something to this effect. It looks through the routes and you could create your own plugin to do it.
wow! this is awesome. Of course, it doesn't work for me as is, as all routes with params (essentially, all routes with `.:format` are ignored). But, it definitely is a great starting point. Looking at the source, it calls for my $app ( Dancer::App->applications ) { my $routes = $app->{registry}->{routes}; This `Dancer::App->applications` array and the routes registry, obviously these are not publicly available methods, so it seems I have to delve into the innards of Dancer to modify/adapt these, no? -- Puneet Kishor
On Fri, Sep 30, 2011 at 10:31 AM, Mr. Puneet Kishor <punk.kish@gmail.com>wrote:
wow! this is awesome. Of course, it doesn't work for me as is, as all routes with params (essentially, all routes with `.:format` are ignored). But, it definitely is a great starting point.
Looking at the source, it calls
for my $app ( Dancer::App->applications ) { my $routes = $app->{registry}->{routes};
This `Dancer::App->applications` array and the routes registry, obviously these are not publicly available methods, so it seems I have to delve into the innards of Dancer to modify/adapt these, no?
I would expect so. I tinkered with it a little bit without too much success but I didn't really delve very deep into it. I was trying to figure out as well how to attach some metadata to a route so I could say what keys were needed but I hadn't figured that out. I expect you can do a Dumper( $app->{registry}->{routes} to really see what you're dealing with for each app.
You want code which will infer what your code is requiring? Sounds tricky, and I doubt you want to run some sort of meta-parser every time someone visits '/rest'. Wouldn't it be easier to write the "resources" data structure (as you have below), maybe as a config file, so you know what your application's interface is, and use that to a) generate responses to /rest, b) maybe generate some documentation, (especially if you include that in the data structure), and c) validate your parameters in the methods, e.g. creating a hash(ref) guaranteed to contain all those and only those parameters specified in the config (and using that hash(ref) thereafter instead of Damcer's parameter function), and then you can guarantee your code complies with the specification. Daniel From: "Mr. Puneet Kishor" <punk.kish@gmail.com> To: dancer-users <dancer-users@perldancer.org> Date: 30/09/2011 14:51 Subject: [Dancer-users] a REST question immediately followed by a Dancer-implementation question Sent by: dancer-users-bounces@perldancer.org So, I have a lot of methods such as get '/foo' => { .. }; get '/bar' => { .. }; get '/baz' => { .. }; get '/qux' => { .. }; All the above methods are reachable via a browser in which they depict some visual representation of the data. Most of the above methods have their '.:format' counterparts, mostly returning JSON packets when reached either via the browser or via the command line. All the methods above return something by default or modified by parameters. So, "http://server/app/foo" may work, or may require some parameters as in " http://server/app/foo?age=27&before=yesterday&for=rascals" I would like to implement a "meta" method, say get '/rest' => { .. }; which should return a listing of all the methods above, along with their parameters, if any, and whether those parameters are optional or required. http://server/app/rest {"resources": [ {"name": "foo, "params": [ {"required": [ {"name": "age", "type": "int"} ]}, {"optional": [ {"name": "before", "type": "string"} {"name": "for", "type": "string"} ]}, ]} ]} In other words, this meta method returns all the resources available at the http://server/app. Of course, I could code this for each app, but it would be nice to automate it. Suggestions? Ideas? -- Puneet Kishor _______________________________________________ Dancer-users mailing list Dancer-users@perldancer.org http://www.backup-manager.org/cgi-bin/listinfo/dancer-users
On Sep 30, 2011, at 11:21 AM, Daniel Perrett wrote:
You want code which will infer what your code is requiring? Sounds tricky,
Perhaps.
and I doubt you want to run some sort of meta-parser every time someone visits '/rest'.
Why not? Without any basis for saying so, I would assert that it wouldn't be very expensive. All depends on how complicated this meta-parser ends up being.
Wouldn't it be easier to write the "resources" data structure (as you have below),
Not necessarily easier, because ...
maybe as a config file, so you know what your application's interface is, and use that to a) generate responses to /rest, b) maybe generate some documentation, (especially if you include that in the data structure), and c) validate your parameters in the methods, e.g. creating a hash(ref) guaranteed to contain all those and only those parameters specified in the config (and using that hash(ref) thereafter instead of Damcer's parameter function), and then you can guarantee your code complies with the specification.
for the simple reason that my "config" file and my application interface will quickly get out of sync (unless I generate one from the other, which is the same as running the meta-parser). Besides, I am writing the app... writing the interface would double my work. If I look at my app code, I can see the interface, so I should be able to infer it programmatically as long as I don't get too ambitious. Ideally, I would like to just add the plugin, and magically get a new route that tells me all the available routes and their params and whether or not those params are required or optional, etc. I looked at the source code for Dancer::Plugin::SiteMap and have already modified it to basically do what I want it to do. It writes out all the routes in JSON format. I have to add the params validate code (I am going ahead and using Params::Validate as that seems to be highly rated). If the plugin ends up being not-too-rough, I would like to release it so perhaps someone else can use it or improve on it. Which brings me to an associated question -- when I get to the point where I can release this modified version of D:P:SiteMap, should I release it as a different plugin? It is clearly generously inspired by that plugin, but is aspiring to do something a bit different. What would be the right thing to do?
Daniel
From: "Mr. Puneet Kishor" <punk.kish@gmail.com> To: dancer-users <dancer-users@perldancer.org> Date: 30/09/2011 14:51 Subject: [Dancer-users] a REST question immediately followed by a Dancer-implementation question Sent by: dancer-users-bounces@perldancer.org
So, I have a lot of methods such as get '/foo' => { .. }; get '/bar' => { .. }; get '/baz' => { .. }; get '/qux' => { .. };
All the above methods are reachable via a browser in which they depict some visual representation of the data.
Most of the above methods have their '.:format' counterparts, mostly returning JSON packets when reached either via the browser or via the command line.
All the methods above return something by default or modified by parameters. So, "http://server/app/foo" may work, or may require some parameters as in " http://server/app/foo?age=27&before=yesterday&for=rascals"
I would like to implement a "meta" method, say
get '/rest' => { .. };
which should return a listing of all the methods above, along with their parameters, if any, and whether those parameters are optional or required.
http://server/app/rest {"resources": [ {"name": "foo, "params": [ {"required": [ {"name": "age", "type": "int"} ]}, {"optional": [ {"name": "before", "type": "string"} {"name": "for", "type": "string"} ]}, ]} ]}
In other words, this meta method returns all the resources available at the http://server/app.
Of course, I could code this for each app, but it would be nice to automate it.
Suggestions? Ideas?
-- Puneet Kishor
My earlier response was too much of the "shot from the hip" variety. Here is a little bit more thought -- On Sep 30, 2011, at 11:32 AM, Mr. Puneet Kishor wrote:
On Sep 30, 2011, at 11:21 AM, Daniel Perrett wrote:
You want code which will infer what your code is requiring? Sounds tricky,
Perhaps.
and I doubt you want to run some sort of meta-parser every time someone visits '/rest'.
Why not? Without any basis for saying so, I would assert that it wouldn't be very expensive. All depends on how complicated this meta-parser ends up being.
Wouldn't it be easier to write the "resources" data structure (as you have below),
Not necessarily easier, because ...
maybe as a config file, so you know what your application's interface is, and use that to a) generate responses to /rest, b) maybe generate some documentation, (especially if you include that in the data structure), and c) validate your parameters in the methods, e.g. creating a hash(ref) guaranteed to contain all those and only those parameters specified in the config (and using that hash(ref) thereafter instead of Damcer's parameter function), and then you can guarantee your code complies with the specification.
for the simple reason that my "config" file and my application interface will quickly get out of sync (unless I generate one from the other, which is the same as running the meta-parser). Besides, I am writing the app... writing the interface would double my work.
If I look at my app code, I can see the interface, so I should be able to infer it programmatically as long as I don't get too ambitious.
Getting the routes themselves is easy. The trick is getting the params, and whether not they are required, and what kind, yadda yadda. If I use Params::Validate, that module tells the user all this info. So, perhaps one approach would be to 1. get all the routes (easy) 2. run all the routes one by one 3. trap the errors from Params::Validate and add them to the routes definitions 4. send the routes definitions with the associated messages from Params::Validate back to the user Comments? Suggestions? -- Puneet Kishor
participants (4)
-
Daniel Perrett -
Dave Doyle -
Mr. Puneet Kishor -
Puneet Kishor